Showing preview only (444K chars total). Download the full file or copy to clipboard to get everything.
Repository: actix/actix
Branch: main
Commit: 3e4318113047
Files: 109
Total size: 415.9 KB
Directory structure:
gitextract_y92ftxtg/
├── .codecov.yml
├── .github/
│ ├── ISSUE_TEMPLATE/
│ │ ├── bug_report.md
│ │ └── config.yml
│ ├── PULL_REQUEST_TEMPLATE.md
│ ├── dependabot.yml
│ └── workflows/
│ ├── ci-post-merge.yml
│ ├── ci.yml
│ ├── clippy-fmt.yml
│ └── coverage.yml
├── .gitignore
├── .prettierrc.yml
├── .rustfmt.toml
├── .vscode/
│ └── settings.json
├── CODE_OF_CONDUCT.md
├── Cargo.toml
├── LICENSE-APACHE
├── LICENSE-MIT
├── actix/
│ ├── CHANGES.md
│ ├── Cargo.toml
│ ├── MIGRATION.md
│ ├── README.md
│ ├── examples/
│ │ ├── README.md
│ │ ├── fibonacci.rs
│ │ ├── mock.rs
│ │ ├── ping.rs
│ │ ├── ring.rs
│ │ ├── weak_addr.rs
│ │ └── weak_recipient.rs
│ ├── src/
│ │ ├── actor.rs
│ │ ├── actors/
│ │ │ ├── mocker.rs
│ │ │ └── mod.rs
│ │ ├── address/
│ │ │ ├── channel.rs
│ │ │ ├── envelope.rs
│ │ │ ├── message.rs
│ │ │ ├── mod.rs
│ │ │ └── queue.rs
│ │ ├── clock.rs
│ │ ├── context.rs
│ │ ├── context_impl.rs
│ │ ├── context_items.rs
│ │ ├── fut/
│ │ │ ├── future/
│ │ │ │ ├── either.rs
│ │ │ │ ├── map.rs
│ │ │ │ ├── mod.rs
│ │ │ │ ├── result.rs
│ │ │ │ ├── then.rs
│ │ │ │ └── timeout.rs
│ │ │ ├── mod.rs
│ │ │ ├── stream/
│ │ │ │ ├── collect.rs
│ │ │ │ ├── finish.rs
│ │ │ │ ├── fold.rs
│ │ │ │ ├── map.rs
│ │ │ │ ├── mod.rs
│ │ │ │ ├── skip_while.rs
│ │ │ │ ├── take_while.rs
│ │ │ │ ├── then.rs
│ │ │ │ └── timeout.rs
│ │ │ └── try_future/
│ │ │ ├── and_then.rs
│ │ │ ├── map_err.rs
│ │ │ ├── map_ok.rs
│ │ │ └── mod.rs
│ │ ├── handler.rs
│ │ ├── io.rs
│ │ ├── lib.rs
│ │ ├── mailbox.rs
│ │ ├── registry.rs
│ │ ├── stream.rs
│ │ ├── supervisor.rs
│ │ ├── sync.rs
│ │ └── utils.rs
│ └── tests/
│ ├── derive.rs
│ ├── test_actor.rs
│ ├── test_address.rs
│ ├── test_arbiter.rs
│ ├── test_atomic_response.rs
│ ├── test_connected.rs
│ ├── test_context.rs
│ ├── test_fut.rs
│ ├── test_lifecycle.rs
│ ├── test_messages.rs
│ ├── test_sink.rs
│ ├── test_supervisor.rs
│ └── test_sync.rs
├── actix-broker/
│ ├── CHANGES.md
│ ├── Cargo.toml
│ ├── LICENSE-APACHE
│ ├── LICENSE-MIT
│ ├── README.md
│ ├── benches/
│ │ └── broker.rs
│ ├── examples/
│ │ ├── actix-web.rs
│ │ └── basic.rs
│ ├── src/
│ │ ├── broker.rs
│ │ ├── issue.rs
│ │ ├── lib.rs
│ │ ├── msgs.rs
│ │ └── subscribe.rs
│ └── tests/
│ ├── delivery.rs
│ └── general.rs
├── actix-derive/
│ ├── CHANGES.md
│ ├── Cargo.toml
│ ├── README.md
│ ├── src/
│ │ ├── lib.rs
│ │ ├── message.rs
│ │ └── message_response.rs
│ └── tests/
│ ├── test_macro.rs
│ ├── trybuild/
│ │ ├── message-response.rs
│ │ ├── message.rs
│ │ └── rt-main.rs
│ └── trybuild.rs
└── justfile
================================================
FILE CONTENTS
================================================
================================================
FILE: .codecov.yml
================================================
comment: false
coverage:
status:
project:
default:
threshold: 100% # make CI green
patch:
default:
threshold: 100% # make CI green
ignore: # ignore code coverage on following paths
- '**/tests'
- '**/benches'
- '**/examples'
================================================
FILE: .github/ISSUE_TEMPLATE/bug_report.md
================================================
---
name: bug report
about: create a bug report
---
Your issue may already be reported! Please search on the [Actix issue tracker](https://github.com/actix/actix/issues) before creating one.
## Expected Behavior
<!--- If you're describing a bug, tell us what should happen -->
<!--- If you're suggesting a change/improvement, tell us how it should work -->
## Current Behavior
<!--- If describing a bug, tell us what happens instead of the expected behavior -->
<!--- If suggesting a change/improvement, explain the difference from current behavior -->
## Possible Solution
<!--- Not obligatory, but suggest a fix/reason for the bug, -->
<!--- or ideas how to implement the addition or change -->
## Steps to Reproduce (for bugs)
<!--- Provide a link to a live example, or an unambiguous set of steps to -->
<!--- reproduce this bug. Include code to reproduce, if relevant -->
1.
2.
3.
4.
## Context
<!--- How has this issue affected you? What are you trying to accomplish? -->
<!--- Providing context helps us come up with a solution that is most useful in the real world -->
## Your Environment
<!--- Include as many relevant details about the environment you experienced the bug in -->
- Rust Version (I.e, output of `rustc -V`):
- Actix Version:
================================================
FILE: .github/ISSUE_TEMPLATE/config.yml
================================================
blank_issues_enabled: true
contact_links:
- name: Actix Discord
url: https://discord.gg/NWpN5mmg3x
about: Actix developer discussion and community chat
================================================
FILE: .github/PULL_REQUEST_TEMPLATE.md
================================================
<!-- Thanks for considering contributing actix! -->
<!-- Please fill out the following to make our reviews easy. -->
## PR Type
<!-- What kind of change does this PR make? -->
<!-- Bug Fix / Feature / Refactor / Code Style / Other -->
INSERT_PR_TYPE
## PR Checklist
Check your PR fulfills the following:
<!-- For draft PRs check the boxes as you complete them. -->
- [ ] Tests for the changes have been added / updated.
- [ ] Documentation comments have been added / updated.
- [ ] A changelog entry has been made for the appropriate packages.
- [ ] Format code with the latest stable rustfmt
## Overview
<!-- Describe the current and new behavior. -->
<!-- Emphasize any breaking changes. -->
<!-- If this PR fixes or closes an issue, reference it here. -->
<!-- Closes #000 -->
================================================
FILE: .github/dependabot.yml
================================================
version: 2
updates:
- package-ecosystem: github-actions
directory: /
schedule:
interval: monthly
- package-ecosystem: cargo
directory: /
schedule:
interval: monthly
versioning-strategy: lockfile-only
groups:
all:
patterns:
- *
================================================
FILE: .github/workflows/ci-post-merge.yml
================================================
name: CI (post-merge)
on:
push:
branches: [main]
permissions:
contents: read
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
jobs:
test_nightly:
strategy:
fail-fast: false
matrix:
# prettier-ignore
target:
- { name: Linux, os: ubuntu-latest, triple: x86_64-unknown-linux-gnu }
- { name: macOS, os: macos-latest, triple: x86_64-apple-darwin }
- { name: Windows, os: windows-latest, triple: x86_64-pc-windows-msvc }
version:
- nightly
name: ${{ matrix.target.name }} / ${{ matrix.version }}
runs-on: ${{ matrix.target.os }}
steps:
- uses: actions/checkout@v6
- name: Setup mold linker
if: matrix.target.os == 'ubuntu-latest'
uses: rui314/setup-mold@v1
- name: Install Rust
uses: actions-rust-lang/setup-rust-toolchain@v1.15.3
with:
toolchain: ${{ matrix.version }}
- name: Install just, cargo-hack, cargo-nextest
uses: taiki-e/install-action@v2
with:
tool: just,cargo-hack,cargo-nextest
- name: Tests
run: just test
timeout-minutes: 10
================================================
FILE: .github/workflows/ci.yml
================================================
name: CI
on:
pull_request:
types: [opened, synchronize, reopened]
merge_group:
types: [checks_requested]
push:
branches: [main]
permissions:
contents: read
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
jobs:
msrv:
name: Read MSRV
uses: actions-rust-lang/msrv/.github/workflows/msrv.yml@v0.1.0
test:
needs: msrv
strategy:
fail-fast: false
matrix:
# prettier-ignore
target:
- { name: Linux, os: ubuntu-latest, triple: x86_64-unknown-linux-gnu }
- { name: macOS, os: macos-latest, triple: x86_64-apple-darwin }
- { name: Windows, os: windows-latest, triple: x86_64-pc-windows-msvc }
version:
- { name: msrv, version: "${{ needs.msrv.outputs.msrv }}" }
- { name: stable, version: stable }
name: ${{ matrix.target.name }} / ${{ matrix.version.name }}
runs-on: ${{ matrix.target.os }}
steps:
- uses: actions/checkout@v6
- name: Setup mold linker
if: matrix.target.os == 'ubuntu-latest'
uses: rui314/setup-mold@v1
- name: Install Rust (${{ matrix.version.name }})
uses: actions-rust-lang/setup-rust-toolchain@v1.15.3
with:
toolchain: ${{ matrix.version.version }}
- name: Install just, cargo-hack, cargo-nextest
uses: taiki-e/install-action@v2.13.5
with:
tool: just,cargo-hack,cargo-nextest
- name: Workaround MSRV issues
if: matrix.version.name == 'msrv'
run: just downgrade-for-msrv
- name: Tests
run: just test
timeout-minutes: 10
doc_test:
name: doctest
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
- name: Install Rust (nightly)
uses: actions-rust-lang/setup-rust-toolchain@v1.15.3
with:
toolchain: nightly
- name: Install just
uses: taiki-e/install-action@v2.13.5
with:
tool: just
- name: Test documentation
run: just test-docs
timeout-minutes: 10
================================================
FILE: .github/workflows/clippy-fmt.yml
================================================
name: Lint
on:
pull_request:
types: [opened, synchronize, reopened]
permissions:
contents: read
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
jobs:
fmt:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
- name: Install Rust
uses: actions-rust-lang/setup-rust-toolchain@v1.15.3
with:
toolchain: nightly
components: rustfmt
- name: Check with rustfmt
run: cargo fmt --all -- --check
clippy:
runs-on: ubuntu-latest
permissions:
checks: write
steps:
- uses: actions/checkout@v6
- name: Install Rust
uses: actions-rust-lang/setup-rust-toolchain@v1.15.3
with:
components: clippy
- name: Check with Clippy
uses: giraffate/clippy-action@v1.0.1
with:
reporter: github-pr-review
github_token: ${{ secrets.GITHUB_TOKEN }}
clippy_flags: --workspace --tests --all-features
================================================
FILE: .github/workflows/coverage.yml
================================================
name: Coverage
on:
push:
branches: [main]
permissions:
contents: read
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
jobs:
coverage:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
- name: Install Rust
uses: actions-rust-lang/setup-rust-toolchain@v1.15.3
with:
components: llvm-tools
- name: Install just, cargo-llvm-cov
uses: taiki-e/install-action@v2.13.4
with:
tool: just,cargo-llvm-cov
- name: Generate code coverage
run: just test-coverage-codecov
- name: Upload coverage to Codecov
uses: codecov/codecov-action@v5.5.2
with:
files: codecov.json
fail_ci_if_error: true
env:
CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
================================================
FILE: .gitignore
================================================
/gh-pages
__pycache__
*.so
*.out
*.pyc
*.pid
*.sock
*~
target/
actix/examples/chat/target/
.idea
/lcov.info
================================================
FILE: .prettierrc.yml
================================================
overrides:
- files: '*.md'
options:
printWidth: 9999
proseWrap: never
- files: '*.{yml,yaml}'
options:
singleQuote: true
printWidth: 100
proseWrap: always
================================================
FILE: .rustfmt.toml
================================================
group_imports = "StdExternalCrate"
imports_granularity = "Crate"
use_field_init_shorthand = true
================================================
FILE: .vscode/settings.json
================================================
{
"cSpell.words": [
"actix",
"bitflags",
"clippy",
"codecov",
"doctest",
"msrv",
"nextest",
"oneshot",
"println",
"rtype",
"rustversion",
"smallvec",
"struct",
"trybuild",
"usize"
]
}
================================================
FILE: CODE_OF_CONDUCT.md
================================================
# Contributor Covenant Code of Conduct
## Our Pledge
In the interest of fostering an open and welcoming environment, we as contributors and maintainers pledge to making participation in our project and our community a harassment-free experience for everyone, regardless of age, body size, disability, ethnicity, gender identity and expression, level of experience, nationality, personal appearance, race, religion, or sexual identity and orientation.
## Our Standards
Examples of behavior that contributes to creating a positive environment include:
- Using welcoming and inclusive language
- Being respectful of differing viewpoints and experiences
- Gracefully accepting constructive criticism
- Focusing on what is best for the community
- Showing empathy towards other community members
Examples of unacceptable behavior by participants include:
- The use of sexualized language or imagery and unwelcome sexual attention or advances
- Trolling, insulting/derogatory comments, and personal or political attacks
- Public or private harassment
- Publishing others' private information, such as a physical or electronic address, without explicit permission
- Other conduct which could reasonably be considered inappropriate in a professional setting
## Our Responsibilities
Project maintainers are responsible for clarifying the standards of acceptable behavior and are expected to take appropriate and fair corrective action in response to any instances of unacceptable behavior.
Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, or to ban temporarily or permanently any contributor for other behaviors that they deem inappropriate, threatening, offensive, or harmful.
## Scope
This Code of Conduct applies both within project spaces and in public spaces when an individual is representing the project or its community. Examples of representing a project or community include using an official project e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event. Representation of a project may be further defined and clarified by project maintainers.
## Enforcement
Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the project team at robjtede@icloud.com ([@robjtede]) or huyuumi@neet.club ([@JohnTitor]). The project team will review and investigate all complaints, and will respond in a way that it deems appropriate to the circumstances. The project team is obligated to maintain confidentiality with regard to the reporter of an incident. Further details of specific enforcement policies may be posted separately.
Project maintainers who do not follow or enforce the Code of Conduct in good faith may face temporary or permanent repercussions as determined by other members of the project's leadership.
[@robjtede]: https://github.com/robjtede
[@JohnTitor]: https://github.com/JohnTitor
## Attribution
This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, available at [http://contributor-covenant.org/version/1/4][version]
[homepage]: http://contributor-covenant.org
[version]: http://contributor-covenant.org/version/1/4/
================================================
FILE: Cargo.toml
================================================
[workspace]
resolver = "2"
members = [
"actix",
"actix-broker",
"actix-derive",
]
[workspace.package]
license = "MIT OR Apache-2.0"
repository = "https://github.com/actix/actix"
edition = "2021"
rust-version = "1.76"
[patch.crates-io]
actix = { path = "actix" }
actix-broker = { path = "actix-broker" }
actix_derive = { path = "actix-derive" }
[profile.release]
lto = true
opt-level = 3
codegen-units = 1
================================================
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 2017-NOW Actix Team
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) 2017 Actix Team
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: actix/CHANGES.md
================================================
# CHANGES
## Unreleased
- Minimum supported Rust version (MSRV) is now 1.76.
## 0.13.5
- Add `Registry::try_get()` method.
- Add `Registry::get_or_start_default()` method.
- Deprecate `Registry::get()` method.
- Relax `A: ArbiterService` bound on `Registry::query()`.
- Relax `A: ArbiterService` bound on `Registry::set()`.
## 0.13.4
- Add `AsyncContext::run_interval_at()` method.
## 0.13.3
- No significant changes since `0.13.2`.
## 0.13.2
- Expose `ContextFut::restart`.
- Unquoted types are now allowed in the `#[rtype(result = TYPE)]` position when type is a path.
## 0.13.1
### Added
- Add `SyncArbiter::start_with_thread_builder()`.
- Derive `PartialEq` and `Eq` for `MailboxError`.
- Minimum supported Rust version (MSRV) is now 1.68.
### Fixed
- Fix `SinkWrite` sometimes not sending all messages in its buffer.
## 0.13.0
### Added
- Add `Sender::downgrade` trait method. [#518]
- Add `Recipient::downgrade` method for obtaining a `WeakRecipient`. [#518]
- Expose `WeakSender` trait. [#518]
- Implement `Clone` for `WeakRecipient`. [#518]
- Implement `From<Recipient>` for `WeakRecipient`. [#518]
- Implement `From<Pin<Box<dyn ActorFuture>>>` for `ActorResponse`. [#509]
- Implement `PartialEq` and `Eq` for `WeakAddr`. [#523]
- Implement `PartialEq` and `Eq` for `WeakAddressSender`. [#523]
- Implement `From<Recipient>` for `WeakRecipient`. [#518]
### Changed
- `Recipient::do_send()` no longer has a return value. [#441]
- Updated `tokio-util` dependency to `0.7`. [#525]
- Updated minimum supported Rust version to 1.54.
### Removed
- Remove `Resolver` actor. [#451]
[#441]: https://github.com/actix/actix/pull/441
[#451]: https://github.com/actix/actix/pull/451
[#509]: https://github.com/actix/actix/pull/509
[#518]: https://github.com/actix/actix/pull/518
[#525]: https://github.com/actix/actix/pull/525
## 0.12.0
### Added
- Add `fut::try_future::ActorTryFuture`. [#419]
- Add `fut::try_future::ActorTryFutureExt` trait with `map_ok`, `map_err` and `and_then` combinator. [#419]
- Add `fut::future::ActorFutureExt::boxed_local` [#493]
- Implemented `MessageResponse` for `Vec<T>` [#501]
### Changed
- Make `Context::new` public. [#491]
- `SinkWriter::write` returns `Result` instead of `Option`. [#499]
[#419]: https://github.com/actix/actix/pull/419
[#491]: https://github.com/actix/actix/pull/491
[#493]: https://github.com/actix/actix/pull/493
[#499]: https://github.com/actix/actix/pull/499
[#501]: https://github.com/actix/actix/pull/501
## 0.11.1
### Fixed
- Panics caused by instant cancellation of a spawned future. [#484]
[#484]: https://github.com/actix/actix/pull/484
## 0.11.0
### Removed
- Remove `fut::IntoActorFuture` trait. [#475]
- Remove `fut::future::WrapFuture`'s `Output` associated type. [#475]
- Remove `fut::stream::WrapStream`'s `Item` associated type. [#475]
- Remove `prelude::Future` re-export from std. [#482]
- Remove `fut::future::Either` re-export. Support for the enum re-exported from `futures_util` enum still exists. [#482]
- Remove `fut::future::FutureResult` type alias. [#482]
[#475]: https://github.com/actix/actix/pull/475
[#479]: https://github.com/actix/actix/pull/479
[#482]: https://github.com/actix/actix/pull/482
## 0.11.0-beta.3
### Added
- Added `fut::{ActorFutureExt, ActorStreamExt}` traits for extension method for `ActorFuture` and `ActorStream` trait. This is aiming to have a similar traits set inline with `futures` crate. [#474]
- Added `ActorStreamExt::collect` method for collect an actor stream's items and output them as an actor future. [#474]
- Added `ActorStreamExt::take_while` method to take an actor stream's items based on the closure output. [#474]
- Added `ActorStreamExt::skip_while` method to skip an actor stream's items based on the closure output. [#474]
- Added `fut::LocalBoxActorFuture` type to keep inline with the `futures::future::LocalBoxFuture` type. [#474]
### Changed
- Rework `fut::future::ActorFuture` trait. [#465]
- `fut::future::{wrap_future, wrap_stream}` would need type annotation for Actor type. [#465]
- `dev::MessageResponse::handle` method does not need generic type [#472]
- `fut::{ok, err, result, FutureResult, Either}` are changed to re-export of `futures::future::{ready, Ready, Either}` types. [#474]
- `futures::future::{ok, err, ready, Ready, Either}` types impls `ActorFuture` trait by default. [#474]
### Removed
- Remove `dev::ResponseChannel` trait. [#472]
[#465]: https://github.com/actix/actix/pull/465
[#472]: https://github.com/actix/actix/pull/472
[#474]: https://github.com/actix/actix/pull/474
## 0.11.0-beta.2
### Changed
- Update `actix-rt` to `v2.0.0`. [#461]
- Feature `resolver` is no longer default. [#461]
- Rename `derive` feature to `macros` since it now includes derive \*and- attribute macros. [#461]
[#421]: https://github.com/actix/actix/pull/421
## 0.11.0-beta.1
### Added
- Re-export `actix_rt::main` macro as `actix::main`. [#448]
- Added `actix::fut::Either::{left, right}()` variant constructors. [#453]
### Changed
- The re-exported `actix-derive` macros are now conditionally included with the `derive` feature which is enabled by default but can be switched off to reduce dependencies. [#424]
- The `where` clause on `Response::fut()` was relaxed to no longer require `T: Unpin`, allowing a `Response` to be created with an `async` block [#421]
- Allow creating `WeakRecipient` from `WeakAddr`, similar to `Recipient` from `Addr`. [#432]
- Send `SyncArbiter` to current `System`'s `Arbiter` and run it as future there. Enables nested `SyncArbiter`s. [#439]
- Use generic type instead of associate type for `EnvelopeProxy`. [#445]
- `SyncEnvelopeProxy` and `SyncContextEnvelope` are no longer bound to an Actor. [#445]
- Rename `actix::clock::{delay_for, delay_until, Delay}` to `{sleep, sleep_until, Sleep}`. [#443]
- Remove all `Unpin` requirement from `ActorStream`. [#443]
- Update examples and tests according to the change of `actix-rt`. `Arbiter::spawn` and `actix_rt::spawn` now panic outside the context of `actix::System`. They must be called inside `System::run`, `SystemRunner::run` or `SystemRunner::block_on`. More information can be found [here](IC717769654). [#447]
- `actix::fut::Either`'s internal variants' representation has changed to struct fields. [#453]
- Replace `pin_project` with `pin_project_lite` [#453]
- Update `crossbeam-channel` to `0.5`
- Update `bytes` to `1`. [#443]
- Update `tokio` to `1`. [#443]
- Update `tokio-util` tp `0.6`. [#443]
### Fixed
- Unified MessageResponse impl (combine separate Item/Error type, migrate to Item=Result). [#446]
- Fix error for build with `--no-default-features` flag, add `sink` feature for futures-util dependency. [#427]
### Removed
- Remove unnecessary `actix::clock::Duration` re-export of `std::time::Duration`. [#443]
[#421]: https://github.com/actix/actix/pull/421
[#424]: https://github.com/actix/actix/pull/424
[#427]: https://github.com/actix/actix/pull/427
[#432]: https://github.com/actix/actix/pull/432
[#435]: https://github.com/actix/actix/pull/435
[#439]: https://github.com/actix/actix/pull/439
[#443]: https://github.com/actix/actix/pull/443
[#445]: https://github.com/actix/actix/pull/445
[#446]: https://github.com/actix/actix/pull/446
[#447]: https://github.com/actix/actix/pull/447
[#448]: https://github.com/actix/actix/pull/448
[#453]: https://github.com/actix/actix/pull/453
[#IC717769654]: https://github.com/actix/actix-net/issues/206#issuecomment-717769654
## 0.10.0
### Changed
- `SinkWrite::write` calls now send all items correctly using an internal buffer. [#384]
- Add `Sync` bound for `Box<dyn Sender>` trait object that making `Recipient` a `Send` + `Sync` type. [#403]
- Update `parking_lot` to 0.11 [#404]
- Remove unnecessary `PhantomData` field from `Request` making it `Send + Sync` regardless if `Request`'s type-argument is `Send` or `Sync` [#407]
[#384]: https://github.com/actix/actix/pull/384
[#403]: https://github.com/actix/actix/pull/403
[#404]: https://github.com/actix/actix/pull/404
[#407]: https://github.com/actix/actix/pull/407
## 0.10.0-alpha.3
### Changed
- Update `tokio-util` dependency to 0.3, `FramedWrite` trait bound is changed. [#365]
- Only poll dropped ContextFut if event loop is running. [#374]
- Minimum Rust version is now 1.40 (to be able to use `#[cfg(doctest)]`)
[#365]: https://github.com/actix/actix/pull/365
[#374]: https://github.com/actix/actix/pull/374
### Fixed
- Fix `ActorFuture::poll_next` impl for `StreamThen` to not lose inner future when it's pending. [#376]
[#376]: https://github.com/actix/actix/pull/376
## 0.10.0-alpha.2
### Added
- New `AtomicResponse`, a `MessageResponse` with exclusive poll over actor's reference. [#357]
### Changed
- Require `Pin` for `ResponseActFuture`. [#355]
[#355]: https://github.com/actix/actix/pull/355
[#357]: https://github.com/actix/actix/pull/357
## 0.10.0-alpha.1
### Fixed
- Fix `MessageResponse` implementation for `ResponseFuture` to always poll the spawned `Future`. [#317]
### Added
- New method address on SyncContext [#341]
- Allow return of any `T: 'static` on `ResponseActFuture`. [#310]
- Allow return of any `T: 'static` on `ResponseFuture`. [#343]
### Changed
- Feature `http` was removed. Actix support for http was moved solely to actix-http and actix-web crates. [#324]
- Make `Pin`s safe [#335] [#346] [#347]
- Only implement `ActorFuture` for `Box` where `ActorFuture` is `Unpin` [#348]
- Upgrade `trust-dns-proto` to 0.19 [#349]
- Upgrade `trust-dns-resolver` to 0.19 [#349]
[#310]: https://github.com/actix/actix/pull/310
[#317]: https://github.com/actix/actix/pull/317
[#324]: https://github.com/actix/actix/pull/324
[#335]: https://github.com/actix/actix/pull/335
[#343]: https://github.com/actix/actix/pull/343
[#346]: https://github.com/actix/actix/pull/346
[#347]: https://github.com/actix/actix/pull/347
[#348]: https://github.com/actix/actix/pull/348
[#349]: https://github.com/actix/actix/pull/349
## 0.9.0
### Fixed
- Fix `ResolveFuture` type signature.
## 0.9.0-alpha.2
### Fixed
- Fix `Resolve` actor's panic
## 0.9.0-alpha.1
### Added
- Added `Context::connected()` to check any addresses are alive
- Added `fut::ready()` future
### Changed
- Migrate to std::future, tokio 0.2 and actix-rt 1.0.0 @bcmcmill #300
- Upgrade `derive_more` to 0.99.2
- Upgrade `smallvec` to 1.0.0
### Fixed
- Added `#[must_use]` attribute to `ActorFuture` and `ActorStream`
## 0.8.3
### Fixed
- Stop actor on async context drop
## 0.8.2
### Changed
- Enable `http` feature by default
## 0.8.1
### Added
- Added `std::error::Error` impl for `SendError`
### Fixed
- Fixed concurrent system registry insert #248
## 0.8.0
### Added
- Added `std::error::Error` impl for `MailboxError`
### Changed
- Use trust-dns-resolver 0.11.0
## 0.8.0.alpha.3
- Add `Actor::start_in_arbiter` with semantics of `Supervisor::start_in_arbiter`.
- Add `ResponseError` for `ResolverError`
- Add `io::SinkWrite`
## 0.8.0-alpha.2
- Add `actix-http` error support for MailboxError
## 0.8.0-alpha.1
### Changes
- Edition 2018
- Replace System/Arbiter with `actix_rt::System` and `actix_rt::Arbiter`
- Add implementations for `Message` for `Arc` and `Box`
- System and arbiter registries available via `from_registry()` method.
### Deleted
- Deleted signals actor. The functionality formerly provided by the signals actor can be achieved using the `tokio-signal` crate. See the [chat example] for how this can work.
[chat example]: ./examples/chat/src/main.rs
## 0.7.10
- Introduced methods `Sender::connected()`, `AddressSender::connected()` and `Recipient::connected()` to check availability of alive actor.
- Added `WeakAddr<A>` to weak reference an actor
## 0.7.9
- Removed `actix` module from prelude. See rationale in #161
## 0.7.8
- Update `crossbeam-channel` to 0.3 and `parking_lot` to 0.7
## 0.7.7
- Impl `Into<Recipient<M>>` for `Addr<A>`
## 0.7.6
- Use `trust-dns-resolver` 0.10.0.
- Make `System::stop_with_code` public.
## 0.7.5
### Added
- Introduce the `clock` module to allow overriding and mocking the system clock based on `tokio_timer`.
- System now has `System::builder()` which allows overriding the system clock with a custom instance. `Arbiter::builder()` can now also override the system clock. The default is to inherit from the system.
- New utility classes `TimerFunc` and `IntervalFunc` in the `utils` module.
- Implement `failure::Fail` for `SendError`.
- Implement `Debug` for multiple public types: `AddressSender`, `Addr`, `Arbiter`, `Context`, `ContextParts`, `ContextFut`, `Response`, `ActorResponse`, `Mailbox`, `SystemRegistry`, `Supervisor`, `System`, `SystemRunner`, `SystemArbiter`. #135
### Changed
- No longer perform unnecessary clone of `Addr` in `SystemRegistry::set`.
- Set min trust-dns version
### Fixed
- fix infinite loop in ContextFut::poll() caused by late cancel_future() #147
## 0.7.4
- Introduce method `query` to determine whether there is running actor in registry.
- Return back `mocker` module.
## 0.7.3
- Parked messages not getting processed #120
## 0.7.2
- Use actix-derive 0.3
## 0.7.1
- Arbiter now has `Arbiter::builder()` which allows opt-in of behavior to stop the actor system on uncaught panic in any arbiter thread. See #111 for examples.
- Allow to set custom system service actor via `SystemRegistry::set()` method.
- `AsyncContext::run_interval` does not fire callback immediately, instead it fires after specified duration.
## 0.7.0
- Context impl refactoring, fix potential UB
- Implemented `Eq`, `PartialEq`, and `Hash` for `actix::Addr`
- Implemented `Eq`, `PartialEq`, and `Hash` for `actix::Recipient`
## 0.6.2
- Breaking change: Restore `StreamHandler` from 0.5, new `StreamHandler` renamed to `StreamHandler2`
## 0.6.1
- Added `actix::run()` and `actix::spawn()` helper functions
- Use parking_lot 0.6
- Fixed potential memory unsafety
## 0.6.0
### Changed
- Use tokio
- `System` and `Arbiter` refactored
- `Arbiter::handle()` is not available anymore. Use `Arbiter::spawn()` and `Arbiter::spawn_fn()` instead.
- `StreamHandler` trait refactored.
- Min rustc version - 1.26
## 0.5.7
- Stop sync actor if sender is dead.
## 0.5.6
- Fix index usage during iteration for future cancellation #67
## 0.5.5
- Fix polling of wrong wait future after completion
## 0.5.4
- Always complete actor lifecycle (i.e. Actor::started())
## 0.5.3
- Panic after cancelling stream future #58
## 0.5.2
- Allow to set timeout for Connect message #56
## 0.5.1
- Internal state is alive during `stopping` period.
- Do not send StopArbiter message to system arbiter during system shutdown #53
## 0.5.0
- Address/Recipient is generic over actor destination
- Make rules of actor stopping more strict
- Use bounded channels for actor communications
- Add dns resolver and tcp connector utility actor
- Add `StreamHandler` trait for stream handling
- Add `Context::handle()` method, currently running future handle
- Add `actix::io` helper types for `AsyncWrite` related types
- Drop FramedContext
## 0.4.5
- Refactor context implementation
- Refactor Supervisor type
- Allow to use `Framed` instances with normal `Context`
## 0.4.4
- Add `Clone` implementation for `Box<Subscriber<M> + Send>`
- Stop stream polling if context is waiting for future completion
- Upgraded address stops working after all references are dropped #38
## 0.4.3
- Cleanup `FramedActor` error and close state handling.
- Do not exit early from framed polling
## 0.4.2
- Cleanup actor stopping process
- Unify context implementation
## 0.4.1
- Remove StreamHandler requirements from add_message_stream()
- Fix items length check
## 0.4.0
- Simplify `Handler` trait (E type removed).
- Use associated type for handler response for `Handler` trait.
- Added framed `drain` method.
- Allow to replace framed object in framed context.
- Enable signal actor by default, make it compatible with windows.
- Added `SyncContext::restart()` method, which allow to restart sync actor.
- Changed behaviour of `Address::call`, if request get drop message cancels.
## 0.3.5
- Re-export `actix_derive` package
- Added conversion implementation `From<Result<I, E>> for Response<A, M>`
- Expose the Framed underneath FramedContext #29
## 0.3.4
- Fix memory leak when sending messages recursively to self #28
- Add convenience impl for boxed Subscriber objects. #27
- Add `ActorStream::fold()` method.
- Add helper combinator `Stream::finish()` method.
## 0.3.3
- SystemRegistry does not store created actor #21
## 0.3.2
- Disable `signal` feature by default
## 0.3.1
- Simplify `ToEnvelope` trait, do not generalize over Message type.
- `ActorContext` requires `ToEnvelope` trait.
- Added `Subscriber::subscriber() -> Box<Subscriber>`
- Simplify `ActorContext` trait, it does not need to know about `Actor`
- Cancel `notify` and `run_later` futures on context stop
## 0.3.0
- Added `Either` future
- Message has to provide `ResponseType` impl instead of Actor
## 0.2.0
- Added `ActorStream`
## 0.1.0 (2017-10-11)
- First release
================================================
FILE: actix/Cargo.toml
================================================
[package]
name = "actix"
version = "0.13.5"
authors = [
"Nikolay Kim <fafhrd91@gmail.com>",
]
description = "Actor framework for Rust"
keywords = ["actor", "futures", "actix", "async", "tokio"]
repository = "https://github.com/actix/actix"
categories = ["network-programming", "asynchronous"]
license = "MIT OR Apache-2.0"
edition.workspace = true
rust-version.workspace = true
[badges]
maintenance.status = "passively-maintained"
[lib]
name = "actix"
path = "src/lib.rs"
[features]
default = ["macros"]
# Re-exports derive macros from actix-derive and enables `#[actix::main]`.
macros = ["actix-macros", "actix_derive"]
# Adds assertion to prevent processing too many messages on event loop
mailbox_assert = []
[dependencies]
actix-macros = { version = "0.2", optional = true }
actix-rt = { version = "2", default-features = false }
actix_derive = { version = "0.6", optional = true }
bitflags = "2"
bytes = "1"
crossbeam-channel = "0.5"
futures-core = { version = "0.3.22", default-features = false }
futures-sink = { version = "0.3.22", default-features = false }
futures-task = { version = "0.3.22", default-features = false }
futures-util = { version = "0.3.22", default-features = false }
log = "0.4"
once_cell = "1.5"
parking_lot = "0.12"
pin-project-lite = "0.2"
smallvec = "1.6.1"
tokio = { version = "1.38.2", features = ["io-util", "sync"] }
tokio-util = { version = "0.7", features = ["codec"] }
[dev-dependencies]
doc-comment = "0.3"
futures-util = { version = "0.3.22", default-features = false, features = ["alloc"] }
[[example]]
name = "fibonacci"
required-features = ["macros"]
[[example]]
name = "ping"
required-features = ["macros"]
[[example]]
name = "weak_addr"
required-features = ["macros"]
[[example]]
name = "weak_recipient"
required-features = ["macros"]
================================================
FILE: actix/MIGRATION.md
================================================
## 0.10.0
- `SinkWrite::write` no longer return a Result, instead it returns an `Option<I>` containing the item that had attempted to be sent if the sink is closing or closed.
Before:
```rust
self.sink.write(data).unwrap();
```
After:
```rust
let _ = self.sink.write(data);
```
## 0.7.9
- `actix` no longer re-exports itself in `actix::prelude` to avoid conflicts with 2018 editions. Please access it through your `extern crate actix` import when necessary
## 0.7.6
- `trust-dns-resolver` dependency was bumped to version 0.10.0. If you use a custom resolver, you will need to switch your `ResolverConfig` and `ResolverOpts` to `trust-dns-resolver` 0.10.0 instead of 0.9.1.
## 0.7
- `Addr` get refactored. `Syn` and `Unsync` removed. all addresses are `Syn` now, only `Addr<Actor>` exists
- `Arbiter` uses `tokio::runtime::current_thread`
- `Arbiter::arbiter()` renamed to `Arbiter::current()`
- `Arbiter::handle()` get removed use `Arbiter::spawn()` instead or you can send `Execute` message to the `System`.
- `Arbiter::system_arbiter()` get removed use `System::arbiter()` instead.
- Use `actix::actors::resolver` instead of `actix::actors::resolver::{Connect, ConnectAddr, Connector, ConnectorError, Resolve};`
- `actix::actors::resolver::Connector` renamed to `actix::actors::resolver::Resolver`
- `actix::actors::resolver::ConnectorError` renamed to `actix::actors::resolver::ResolverError`
================================================
FILE: actix/README.md
================================================
<div align="center">
<h1>Actix</h1>
<p>
<strong>Actor framework for Rust</strong>
</p>
<p>
<!-- prettier-ignore-start -->
[](https://crates.io/crates/actix)
[](https://docs.rs/actix/0.13.5)


[](https://deps.rs/crate/actix/0.13.5)
<br />
[](https://github.com/actix/actix/actions/workflows/ci.yml)
[](https://codecov.io/gh/actix/actix)

[](https://discord.gg/GMuKN5b8aR)
<!-- prettier-ignore-end -->
</p>
</div>
## Documentation
- [User Guide](https://actix.rs/docs/actix)
- [API Documentation](https://docs.rs/actix)
## Features
- Async and sync actors
- Actor communication in a local/thread context
- Uses [futures](https://crates.io/crates/futures) for asynchronous message handling
- Actor supervision
- Typed messages (No `Any` type)
- Runs on stable Rust 1.76+
## Usage
To use `actix`, add this to your `Cargo.toml`:
```toml
[dependencies]
actix = "0.13"
```
### Initialize Actix
In order to use actix you first need to create a `System`.
```rust,ignore
fn main() {
let system = actix::System::new();
system.run();
}
```
Actix uses the [Tokio](https://github.com/tokio-rs/tokio) runtime. `System::new()` creates a new event loop. `System.run()` starts the Tokio event loop, and will finish once the `System` actor receives the `SystemExit` message.
### Implementing an Actor
In order to define an actor you need to define a struct and have it implement the [`Actor`](https://docs.rs/actix/latest/actix/trait.Actor.html) trait.
```rust
use actix::{Actor, Context, System};
struct MyActor;
impl Actor for MyActor {
type Context = Context<Self>;
fn started(&mut self, _ctx: &mut Self::Context) {
println!("I am alive!");
System::current().stop(); // <- stop system
}
}
fn main() {
let system = System::new();
let _addr = system.block_on(async { MyActor.start() });
system.run().unwrap();
}
```
Spawning a new actor is achieved via the `start` and `create` methods of the [Actor trait]. It provides several different ways of creating actors; for details, check the docs. You can implement the `started`, `stopping` and `stopped` methods of the Actor trait. `started` gets called when the actor starts and `stopping` when the actor finishes. Check the API docs for more information on [the actor lifecycle].
[Actor trait]: https://docs.rs/actix/latest/actix/trait.Actor.html
[the actor lifecycle]: https://actix.rs/docs/actix/actor#actor-lifecycle
### Handle Messages
An Actor communicates with another Actor by sending messages. In actix all messages are typed. Let's define a simple `Sum` message with two `usize` parameters and an actor which will accept this message and return the sum of those two numbers. Here we use the `#[actix::main]` attribute as an easier way to start our `System` and drive our main function so we can easily `.await` for the responses sent back from the `Actor`.
```rust
use actix::prelude::*;
// this is our Message
// we have to define the response type (rtype)
#[derive(Message)]
#[rtype(usize)]
struct Sum(usize, usize);
// Actor definition
struct Calculator;
impl Actor for Calculator {
type Context = Context<Self>;
}
// now we need to implement `Handler` on `Calculator` for the `Sum` message.
impl Handler<Sum> for Calculator {
type Result = usize; // <- Message response type
fn handle(&mut self, msg: Sum, _ctx: &mut Context<Self>) -> Self::Result {
msg.0 + msg.1
}
}
#[actix::main] // <- starts the system and block until future resolves
async fn main() {
let addr = Calculator.start();
let res = addr.send(Sum(10, 5)).await; // <- send message and get future for result
match res {
Ok(result) => println!("SUM: {}", result),
_ => println!("Communication to the actor has failed"),
}
}
```
All communications with actors go through an `Addr` object. You can `do_send` a message without waiting for a response, or you can `send` an actor a specific message. The `Message` trait defines the result type for a message.
### Actor State And Subscription For Specific Messages
You may have noticed that the methods of the `Actor` and `Handler` traits accept `&mut self`, so you are welcome to store anything in an actor and mutate it whenever necessary.
Address objects require an actor type, but if we just want to send a specific message to an actor that can handle the message, we can use the `Recipient` interface. Let's create a new actor that uses `Recipient`.
```rust
use actix::prelude::*;
use std::time::Duration;
#[derive(Message)]
#[rtype(result = "()")]
struct Ping {
pub id: usize,
}
// Actor definition
struct Game {
counter: usize,
name: String,
recipient: Recipient<Ping>,
}
impl Actor for Game {
type Context = Context<Game>;
}
// simple message handler for Ping message
impl Handler<Ping> for Game {
type Result = ();
fn handle(&mut self, msg: Ping, ctx: &mut Context<Self>) {
self.counter += 1;
if self.counter > 10 {
System::current().stop();
} else {
println!("[{0}] Ping received {1}", self.name, msg.id);
// wait 100 nanoseconds
ctx.run_later(Duration::new(0, 100), move |act, _| {
act.recipient.do_send(Ping { id: msg.id + 1 });
});
}
}
}
fn main() {
let system = System::new();
system.block_on(async {
// To create a cyclic game link, we need to use a different constructor
// method to get access to its recipient before it starts.
let _game = Game::create(|ctx| {
// now we can get an address of the first actor and create the second actor
let addr = ctx.address();
let addr2 = Game {
counter: 0,
name: String::from("Game 2"),
recipient: addr.recipient(),
}
.start();
// let's start pings
addr2.do_send(Ping { id: 10 });
// now we can finally create first actor
Game {
counter: 0,
name: String::from("Game 1"),
recipient: addr2.recipient(),
}
});
});
// let the actors all run until they've shut themselves down
system.run().unwrap();
}
```
### Chat Example
See this [chat example] which shows more comprehensive usage in a networking client/server service.
[chat example]: https://github.com/actix/examples/tree/HEAD/websockets/chat-tcp
## Contributing
All contributions are welcome, if you have a feature request don't hesitate to open an issue!
## License
This project is licensed under either of
- Apache License, Version 2.0, ([LICENSE-APACHE](LICENSE-APACHE) or https://www.apache.org/licenses/LICENSE-2.0)
- MIT license ([LICENSE-MIT](LICENSE-MIT) or https://opensource.org/licenses/MIT)
at your option.
## Code of Conduct
Contribution to the actix repo is organized under the terms of the Contributor Covenant. The Actix team promises to intervene to uphold that code of conduct.
================================================
FILE: actix/examples/README.md
================================================
# Actix Examples
The following examples complement the documentation and can help you understand how to use Actix:
1. [Ping](https://github.com/actix/actix/blob/HEAD/actix/examples/ping.rs) - Basic example showing 2 actors playing ping/pong.
2. [Fibonacci](https://github.com/actix/actix/blob/HEAD/actix/examples/fibonacci.rs) - Demonstrates how to integrate a synchronous actor on a thread-pool for cpu bound tasks.
3. [Ring](https://github.com/actix/actix/blob/HEAD/actix/examples/ring.rs) - Ring benchmark inspired by Programming Erlang: Software for a Concurrent World. Send a M messages round a ring of N actors and benchmark.
4. [Chat](https://github.com/actix/examples/tree/HEAD/websockets/chat-tcp) - More realistic application example of a chat server/client.
5. [Mock](https://github.com/actix/actix/tree/HEAD/actix/examples/mock.rs) - Example on how to use the mocking utility ator.
================================================
FILE: actix/examples/fibonacci.rs
================================================
//! Example of sync actor. It can be used for cpu bound tasks. Only one sync
//! actor runs within arbiter's thread. Sync actor processes one message at a
//! time. Sync arbiter can start multiple threads with separate instance of
//! actor in each.
use actix::prelude::*;
struct Fibonacci(pub u32);
impl Message for Fibonacci {
type Result = Result<u64, ()>;
}
struct SyncActor;
impl Actor for SyncActor {
type Context = SyncContext<Self>;
}
impl Handler<Fibonacci> for SyncActor {
type Result = Result<u64, ()>;
fn handle(&mut self, msg: Fibonacci, _: &mut Self::Context) -> Self::Result {
if msg.0 == 0 {
Err(())
} else if msg.0 == 1 {
Ok(1)
} else {
let mut i = 0;
let mut sum = 0;
let mut last = 0;
let mut curr = 1;
while i < msg.0 - 1 {
sum = last + curr;
last = curr;
curr = sum;
i += 1;
}
Ok(sum)
}
}
}
#[actix::main]
async fn main() {
// start sync arbiter with 3 threads
let addr = SyncArbiter::start(3, || SyncActor);
// send 5 messages
for n in 5..10 {
println!("{:?}", addr.send(Fibonacci(n)).await.unwrap());
}
System::current().stop();
}
================================================
FILE: actix/examples/mock.rs
================================================
//! Mock example
//!
//! Mocking an actor and setting it on the `SystemRegistry`. This can be
//! done so you can test an actor that depends on a `SystemService` in isolation.
#[cfg(test)]
use actix::actors::mocker::Mocker;
use actix::prelude::*;
#[cfg(test)]
use actix::SystemRegistry;
#[derive(Default)]
struct MyActor {}
impl Actor for MyActor {
type Context = Context<Self>;
}
impl Handler<Question> for MyActor {
type Result = ResponseFuture<usize>;
fn handle(&mut self, _msg: Question, _ctx: &mut Context<Self>) -> Self::Result {
let act_addr = AnswerActor::from_registry();
let request = act_addr.send(Question {});
Box::pin(async move { request.await.unwrap() })
}
}
#[derive(Default)]
struct AnsActor {}
#[derive(Message)]
#[rtype(usize)]
struct Question {}
#[cfg(not(test))]
type AnswerActor = AnsActor;
#[cfg(test)]
type AnswerActor = Mocker<AnsActor>;
impl Actor for AnsActor {
type Context = Context<Self>;
}
impl Supervised for AnsActor {}
impl SystemService for AnsActor {}
impl Handler<Question> for AnsActor {
type Result = usize;
fn handle(&mut self, _: Question, _: &mut Context<Self>) -> Self::Result {
42
}
}
#[actix::main]
async fn main() {
let addr = MyActor::default().start();
let result = addr.send(Question {}).await.unwrap_or_default();
assert_eq!(42, result);
}
#[cfg(test)]
mod tests {
use super::*;
#[actix::test]
async fn mocked_behavior() {
let mocker_addr = AnswerActor::mock(Box::new(move |_msg, _ctx| {
let result: usize = 2;
Box::new(Some(result))
}))
.start();
SystemRegistry::set(mocker_addr);
let result = MyActor::default().start().send(Question {}).await.unwrap();
assert_eq!(result, 2);
}
}
================================================
FILE: actix/examples/ping.rs
================================================
use actix::prelude::*;
/// Define `Ping` message
struct Ping(usize);
impl Message for Ping {
type Result = usize;
}
/// Actor
struct MyActor {
count: usize,
}
/// Declare actor and its context
impl Actor for MyActor {
type Context = Context<Self>;
}
/// Handler for `Ping` message
impl Handler<Ping> for MyActor {
type Result = usize;
fn handle(&mut self, msg: Ping, _: &mut Context<Self>) -> Self::Result {
self.count += msg.0;
self.count
}
}
#[actix::main]
async fn main() {
// start new actor
let addr = MyActor { count: 10 }.start();
// send message and get future for result
let res = addr.send(Ping(10)).await;
// handle() returns tokio handle
println!("RESULT: {}", res.unwrap() == 20);
// stop system and exit
System::current().stop();
}
================================================
FILE: actix/examples/ring.rs
================================================
//! Ring benchmark inspired by Programming Erlang: Software for a
//! Concurrent World, by Joe Armstrong, Chapter 8.11.2
//!
//! "Write a ring benchmark. Create N processes in a ring. Send a
//! message round the ring M times so that a total of N * M messages
//! get sent. Time how long this takes for different values of N and M."
use std::{env, io, time::SystemTime};
use actix::prelude::*;
/// A payload with a counter
#[derive(Debug, Message)]
#[rtype(result = "()")]
struct Payload(usize);
#[derive(Debug)]
struct Node {
id: usize,
limit: usize,
next: Recipient<Payload>,
}
impl Actor for Node {
type Context = Context<Self>;
}
impl Handler<Payload> for Node {
type Result = ();
fn handle(&mut self, msg: Payload, _: &mut Context<Self>) {
if msg.0 >= self.limit {
println!(
"Actor {} reached limit of {} (payload was {})",
self.id, self.limit, msg.0
);
System::current().stop();
return;
}
// Some prime in order for different actors to report progress.
// Large enough to print about once per second in debug mode.
if msg.0 % 498989 == 1 {
println!(
"Actor {} received message {} of {} ({:.2}%)",
self.id,
msg.0,
self.limit,
100.0 * msg.0 as f32 / self.limit as f32
);
}
self.next.do_send(Payload(msg.0 + 1));
}
}
fn main() -> io::Result<()> {
let sys = System::new();
let (n_nodes, n_rounds) = parse_args();
let now = SystemTime::now();
sys.block_on(async {
println!("Setting up {} nodes", n_nodes);
let limit = n_nodes * n_rounds;
let node = Node::create(move |ctx| {
let first_addr = ctx.address();
let mut prev_addr = Node {
id: 1,
limit,
next: first_addr.recipient(),
}
.start();
for id in 2..n_nodes {
prev_addr = Node {
id,
limit,
next: prev_addr.recipient(),
}
.start();
}
Node {
id: n_nodes,
limit,
next: prev_addr.recipient(),
}
});
println!(
"Sending start message and waiting for termination after {} messages...",
limit
);
node.send(Payload(1)).await.unwrap();
});
sys.run().unwrap();
match now.elapsed() {
Ok(elapsed) => println!(
"Time taken: {}.{:06} seconds ({} msg/second)",
elapsed.as_secs(),
elapsed.subsec_micros(),
(n_nodes * n_rounds * 1000000) as u128 / elapsed.as_micros()
),
Err(e) => println!("An error occurred: {:?}", e),
}
Ok(())
}
fn parse_args() -> (usize, usize) {
let mut args = env::args();
// skip first arg
args.next();
let n_nodes = args
.next()
.and_then(|val| val.parse::<usize>().ok())
.unwrap_or_else(|| print_usage_and_exit());
if n_nodes <= 1 {
eprintln!("Number of nodes must be > 1");
::std::process::exit(1);
}
let n_rounds = args
.next()
.and_then(|val| val.parse::<usize>().ok())
.unwrap_or_else(|| print_usage_and_exit());
if args.next().is_some() {
print_usage_and_exit();
}
(n_nodes, n_rounds)
}
fn print_usage_and_exit() -> ! {
eprintln!("Usage:");
eprintln!("cargo run --example ring -- <num-nodes> <num-times-message-around-ring>");
::std::process::exit(1);
}
================================================
FILE: actix/examples/weak_addr.rs
================================================
//! WeakAddr example
//!
//! With a weak address you can register an client actor's addrs with a
//! service and still get cleaned up correctly when the client actor is
//! stopped. Alternatively you'd have to check if the client's mailbox
//! is still open.
use std::time::{Duration, Instant};
use actix::{prelude::*, WeakAddr};
#[derive(Message, Debug)]
#[rtype(result = "()")]
pub struct TimePing(Instant);
#[derive(Message, Debug)]
#[rtype(result = "()")]
pub struct RegisterForTime(pub WeakAddr<Client>);
#[derive(Debug, Default)]
pub struct TimeService {
clients: Vec<WeakAddr<Client>>,
}
impl TimeService {
fn send_tick(&mut self, _ctx: &mut Context<Self>) {
for client in self.clients.iter() {
if let Some(client) = client.upgrade() {
client.do_send(TimePing(Instant::now()));
println!("⏰ sent ping to client {:?}", client);
} else {
println!("⏰ client can no longer be upgraded");
}
}
// gc
self.clients = self
.clients
.drain(..)
.filter(|c| c.upgrade().is_some())
.collect();
println!("⏰ service has {} clients", self.clients.len());
}
}
impl Actor for TimeService {
type Context = Context<Self>;
fn started(&mut self, ctx: &mut Self::Context) {
println!("⏰ starting TimeService");
ctx.run_interval(Duration::from_millis(1_000), Self::send_tick);
}
fn stopping(&mut self, _ctx: &mut Self::Context) -> Running {
println!("⏰ stopping TimeService");
Running::Stop
}
fn stopped(&mut self, _ctx: &mut Self::Context) {
println!("⏰ stopped TimeService");
}
}
impl Handler<RegisterForTime> for TimeService {
type Result = ();
fn handle(
&mut self,
RegisterForTime(client): RegisterForTime,
_ctx: &mut Self::Context,
) -> Self::Result {
println!("⏰ received registration");
self.clients.push(client);
}
}
impl Supervised for TimeService {}
impl SystemService for TimeService {}
#[derive(Debug, Default)]
pub struct Client;
impl Actor for Client {
type Context = Context<Self>;
fn started(&mut self, ctx: &mut Self::Context) {
println!("🐰 starting Client");
TimeService::from_registry()
.send(RegisterForTime(ctx.address().downgrade()))
.into_actor(self)
.then(|_, _slf, _| fut::ready(()))
.spawn(ctx);
}
fn stopping(&mut self, _ctx: &mut Self::Context) -> Running {
println!("🐰 stopping Client");
Running::Stop
}
fn stopped(&mut self, _ctx: &mut Self::Context) {
println!("🐰 stopped Client");
}
}
impl Handler<TimePing> for Client {
type Result = ();
fn handle(&mut self, msg: TimePing, _ctx: &mut Self::Context) -> Self::Result {
println!("🐰 client received ping: {:?}", msg.0);
}
}
#[actix::main]
async fn main() {
{
println!("🎩 creating client client");
let _client = Client.start();
println!("🎩 press Ctrl-C to stop client");
tokio::signal::ctrl_c().await.unwrap();
println!("🎩 Ctrl-C received, stopping client");
}
tokio::signal::ctrl_c().await.unwrap();
println!("🎩 Ctrl-C received, shutting down");
System::current().stop();
}
================================================
FILE: actix/examples/weak_recipient.rs
================================================
//! WeakRecipient example
//!
//! With a weak recipient you can register any client actor's addrs with a
//! service and still get cleaned up correctly when the client actor is
//! stopped. In contrast to a `WeakAddr` the Service is not bound to know
//! exactly which type of client actor is registering itself.
use std::time::{Duration, Instant};
use actix::{prelude::*, WeakRecipient};
#[derive(Message, Debug)]
#[rtype(result = "()")]
pub struct TimePing(Instant);
#[derive(Message, Debug)]
#[rtype(result = "()")]
pub struct RegisterForTime(pub WeakRecipient<TimePing>);
#[derive(Debug, Default)]
pub struct TimeService {
clients: Vec<WeakRecipient<TimePing>>,
}
impl TimeService {
fn send_tick(&mut self, _ctx: &mut Context<Self>) {
for client in self.clients.iter() {
if let Some(client) = client.upgrade() {
client.do_send(TimePing(Instant::now()));
println!("⏰ sent ping to client {:?}", client);
} else {
println!("⏰ client can no longer be upgraded");
}
}
// gc
self.clients = self
.clients
.drain(..)
.filter(|c| c.upgrade().is_some())
.collect();
println!("⏰ service has {} clients", self.clients.len());
}
}
impl Actor for TimeService {
type Context = Context<Self>;
fn started(&mut self, ctx: &mut Self::Context) {
println!("⏰ starting TimeService");
ctx.run_interval(Duration::from_millis(1_000), Self::send_tick);
}
fn stopping(&mut self, _ctx: &mut Self::Context) -> Running {
println!("⏰ stopping TimeService");
Running::Stop
}
fn stopped(&mut self, _ctx: &mut Self::Context) {
println!("⏰ stopped TimeService");
}
}
impl Handler<RegisterForTime> for TimeService {
type Result = ();
fn handle(
&mut self,
RegisterForTime(client): RegisterForTime,
_ctx: &mut Self::Context,
) -> Self::Result {
println!("⏰ received registration");
self.clients.push(client);
}
}
impl Supervised for TimeService {}
impl SystemService for TimeService {}
#[derive(Debug, Default)]
pub struct ClientA;
impl Actor for ClientA {
type Context = Context<Self>;
fn started(&mut self, ctx: &mut Self::Context) {
println!("🐰 starting ClientA");
TimeService::from_registry()
.send(RegisterForTime(ctx.address().downgrade().recipient()))
.into_actor(self)
.then(|_, _slf, _| fut::ready(()))
.spawn(ctx);
}
fn stopping(&mut self, _ctx: &mut Self::Context) -> Running {
println!("🐰 stopping ClientA");
Running::Stop
}
fn stopped(&mut self, _ctx: &mut Self::Context) {
println!("🐰 stopped ClientA");
}
}
impl Handler<TimePing> for ClientA {
type Result = ();
fn handle(&mut self, msg: TimePing, _ctx: &mut Self::Context) -> Self::Result {
println!("🐰 ClientA received ping: {:?}", msg.0);
}
}
#[derive(Debug, Default)]
pub struct ClientB;
impl Actor for ClientB {
type Context = Context<Self>;
fn started(&mut self, ctx: &mut Self::Context) {
println!("🐇 starting ClientB");
TimeService::from_registry()
.send(RegisterForTime(ctx.address().downgrade().recipient()))
.into_actor(self)
.then(|_, _slf, _| fut::ready(()))
.spawn(ctx);
}
fn stopping(&mut self, _ctx: &mut Self::Context) -> Running {
println!("🐇 stopping ClientB");
Running::Stop
}
fn stopped(&mut self, _ctx: &mut Self::Context) {
println!("🐇 stopped ClientB");
}
}
impl Handler<TimePing> for ClientB {
type Result = ();
fn handle(&mut self, msg: TimePing, _ctx: &mut Self::Context) -> Self::Result {
println!("🐇 ClientB received ping: {:?}", msg);
}
}
#[actix::main]
async fn main() {
{
println!("🎩 creating client client A");
let _client_a = ClientA.start();
{
println!("🎩 creating client client B");
let _client_b = ClientB.start();
println!("🎩 press Ctrl-C to stop client B");
tokio::signal::ctrl_c().await.unwrap();
println!("🎩 Ctrl-C received, stopping client");
}
println!("🎩 press Ctrl-C to stop client A");
tokio::signal::ctrl_c().await.unwrap();
println!("🎩 Ctrl-C received, stopping client");
}
tokio::signal::ctrl_c().await.unwrap();
println!("🎩 Ctrl-C received, shutting down");
System::current().stop();
}
================================================
FILE: actix/src/actor.rs
================================================
use std::time::Duration;
use actix_rt::ArbiterHandle;
use futures_core::stream::Stream;
use log::error;
use crate::{
address::{channel, Addr},
context::Context,
context_items::{ActorDelayedMessageItem, ActorMessageItem, ActorMessageStreamItem},
fut::{ActorFuture, ActorStreamExt},
handler::{Handler, Message},
mailbox::DEFAULT_CAPACITY,
stream::StreamHandler,
utils::{IntervalFunc, TimerFunc},
};
/// Actors are objects which encapsulate state and behavior.
///
/// Actors run within a specific execution context
/// [`Context<A>`](struct.Context.html). The context object is available
/// only during execution. Each actor has a separate execution
/// context. The execution context also controls the lifecycle of an
/// actor.
///
/// Actors communicate exclusively by exchanging messages. The sender
/// actor can wait for a response. Actors are not referenced directly,
/// but by address [`Addr`](struct.Addr.html) To be able to handle a
/// specific message actor has to provide a
/// [`Handler<M>`](trait.Handler.html) implementation for this
/// message. All messages are statically typed. A message can be
/// handled in asynchronous fashion. An actor can spawn other actors
/// or add futures or streams to the execution context. The actor
/// trait provides several methods that allow controlling the actor
/// lifecycle.
///
/// # Actor lifecycle
///
/// ## Started
///
/// An actor starts in the `Started` state, during this state the
/// `started` method gets called.
///
/// ## Running
///
/// After an actor's `started` method got called, the actor
/// transitions to the `Running` state. An actor can stay in the
/// `running` state for an indefinite amount of time.
///
/// ## Stopping
///
/// The actor's execution state changes to `stopping` in the following
/// situations:
///
/// * `Context::stop` gets called by actor itself
/// * all addresses to the actor get dropped
/// * no evented objects are registered in its context.
///
/// An actor can return from the `stopping` state to the `running`
/// state by creating a new address or adding an evented object, like
/// a future or stream, in its `Actor::stopping` method.
///
/// If an actor changed to a `stopping` state because
/// `Context::stop()` got called, the context then immediately stops
/// processing incoming messages and calls the `Actor::stopping()`
/// method. If an actor does not return back to a `running` state,
/// all unprocessed messages get dropped.
///
/// ## Stopped
///
/// If an actor does not modify execution context while in stopping
/// state, the actor state changes to `Stopped`. This state is
/// considered final and at this point the actor gets dropped.
#[allow(unused_variables)]
pub trait Actor: Sized + Unpin + 'static {
/// Actor execution context type
type Context: ActorContext;
/// Called when an actor gets polled the first time.
fn started(&mut self, ctx: &mut Self::Context) {}
/// Called after an actor is in `Actor::Stopping` state.
///
/// There can be several reasons for stopping:
///
/// - `Context::stop` gets called by the actor itself.
/// - All addresses to the current actor get dropped and no more
/// evented objects are left in the context.
///
/// An actor can return from the stopping state to the running
/// state by returning `Running::Continue`.
fn stopping(&mut self, ctx: &mut Self::Context) -> Running {
Running::Stop
}
/// Called after an actor is stopped.
///
/// This method can be used to perform any needed cleanup work or
/// to spawn more actors. This is the final state, after this
/// method got called, the actor will be dropped.
fn stopped(&mut self, ctx: &mut Self::Context) {}
/// Start a new asynchronous actor, returning its address.
///
/// # Examples
///
/// ```
/// use actix::prelude::*;
///
/// struct MyActor;
/// impl Actor for MyActor {
/// type Context = Context<Self>;
/// }
///
/// #[actix::main]
/// async fn main() {
/// // start actor and get its address
/// let addr = MyActor.start();
/// # System::current().stop();
/// }
/// ```
fn start(self) -> Addr<Self>
where
Self: Actor<Context = Context<Self>>,
{
Context::new().run(self)
}
/// Construct and start a new asynchronous actor, returning its
/// address.
///
/// This is constructs a new actor using the `Default` trait, and
/// invokes its `start` method.
fn start_default() -> Addr<Self>
where
Self: Actor<Context = Context<Self>> + Default,
{
Self::default().start()
}
/// Start new actor in arbiter's thread.
fn start_in_arbiter<F>(wrk: &ArbiterHandle, f: F) -> Addr<Self>
where
Self: Actor<Context = Context<Self>>,
F: FnOnce(&mut Context<Self>) -> Self + Send + 'static,
{
let (tx, rx) = channel::channel(DEFAULT_CAPACITY);
// create actor
wrk.spawn_fn(move || {
let mut ctx = Context::with_receiver(rx);
let act = f(&mut ctx);
let fut = ctx.into_future(act);
actix_rt::spawn(fut);
});
Addr::new(tx)
}
/// Start a new asynchronous actor given a `Context`.
///
/// Use this method if you need the `Context` object during actor
/// initialization.
///
/// # Examples
///
/// ```
/// use actix::prelude::*;
///
/// struct MyActor {
/// val: usize,
/// }
/// impl Actor for MyActor {
/// type Context = Context<Self>;
/// }
///
/// #[actix::main]
/// async fn main() {
/// let addr = MyActor::create(|ctx: &mut Context<MyActor>| MyActor { val: 10 });
/// # System::current().stop();
/// }
/// ```
fn create<F>(f: F) -> Addr<Self>
where
Self: Actor<Context = Context<Self>>,
F: FnOnce(&mut Context<Self>) -> Self,
{
let mut ctx = Context::new();
let act = f(&mut ctx);
ctx.run(act)
}
}
#[allow(unused_variables)]
/// Actors with the ability to restart after failure.
///
/// Supervised actors can be managed by a
/// [`Supervisor`](struct.Supervisor.html). As an additional lifecycle
/// event, the `restarting` method can be implemented.
///
/// If a supervised actor fails, its supervisor creates new execution
/// context and restarts the actor, invoking its `restarting` method.
/// After a call to this method, the actor's execution state changes
/// to `Started` and the regular lifecycle process starts.
///
/// The `restarting` method gets called with the newly constructed
/// `Context` object.
pub trait Supervised: Actor {
/// Called when the supervisor restarts a failed actor.
fn restarting(&mut self, ctx: &mut <Self as Actor>::Context) {}
}
/// Actor execution state
#[derive(PartialEq, Debug, Copy, Clone)]
pub enum ActorState {
/// Actor is started.
Started,
/// Actor is running.
Running,
/// Actor is stopping.
Stopping,
/// Actor is stopped.
Stopped,
}
#[derive(Clone, Copy, Debug, PartialEq)]
pub enum Running {
Stop,
Continue,
}
impl ActorState {
/// Indicates whether the actor is alive.
pub fn alive(self) -> bool {
self == ActorState::Started || self == ActorState::Running
}
/// Indicates whether the actor is stopped or stopping.
pub fn stopping(self) -> bool {
self == ActorState::Stopping || self == ActorState::Stopped
}
}
/// Actor execution context.
///
/// Each actor runs within a specific execution context. The actor's
/// associated type `Actor::Context` defines the context to use for
/// the actor, and must implement the `ActorContext` trait.
///
/// The execution context defines the type of execution, and the
/// actor's communication channels (message handling).
pub trait ActorContext: Sized {
/// Immediately stop processing incoming messages and switch to a
/// `stopping` state. This only affects actors that are currently
/// `running`. Future attempts to queue messages will fail.
fn stop(&mut self);
/// Terminate actor execution unconditionally. This sets the actor
/// into the `stopped` state. This causes future attempts to queue
/// messages to fail.
fn terminate(&mut self);
/// Retrieve the current Actor execution state.
fn state(&self) -> ActorState;
}
/// Asynchronous execution context.
pub trait AsyncContext<A>: ActorContext
where
A: Actor<Context = Self>,
{
/// Returns the address of the context.
fn address(&self) -> Addr<A>;
/// Spawns a future into the context.
///
/// Returns a handle of the spawned future, which can be used for
/// cancelling its execution.
///
/// All futures spawned into an actor's context are cancelled
/// during the actor's stopping stage.
fn spawn<F>(&mut self, fut: F) -> SpawnHandle
where
F: ActorFuture<A, Output = ()> + 'static;
/// Spawns a future into the context, waiting for it to resolve.
///
/// This stops processing any incoming events until the future
/// resolves.
fn wait<F>(&mut self, fut: F)
where
F: ActorFuture<A, Output = ()> + 'static;
/// Checks if the context is paused (waiting for future completion or stopping).
fn waiting(&self) -> bool;
/// Cancels a spawned future.
///
/// The `handle` is a value returned by the `spawn` method.
fn cancel_future(&mut self, handle: SpawnHandle) -> bool;
/// Registers a stream with the context.
///
/// This allows handling a `Stream` in a way similar to normal
/// actor messages.
///
/// ```
/// # use std::io;
/// use actix::prelude::*;
/// use futures_util::stream::once;
///
/// #[derive(Message)]
/// #[rtype(result = "()")]
/// struct Ping;
///
/// struct MyActor;
///
/// impl StreamHandler<Ping> for MyActor {
///
/// fn handle(&mut self, item: Ping, ctx: &mut Context<MyActor>) {
/// println!("PING");
/// System::current().stop();
/// }
///
/// fn finished(&mut self, ctx: &mut Self::Context) {
/// println!("finished");
/// }
/// }
///
/// impl Actor for MyActor {
/// type Context = Context<Self>;
///
/// fn started(&mut self, ctx: &mut Context<Self>) {
/// // add stream
/// ctx.add_stream(once(async { Ping }));
/// }
/// }
///
/// fn main() {
/// let mut sys = System::new();
/// let addr = sys.block_on(async { MyActor.start() });
/// sys.run();
/// }
/// ```
fn add_stream<S>(&mut self, fut: S) -> SpawnHandle
where
S: Stream + 'static,
A: StreamHandler<S::Item>,
{
<A as StreamHandler<S::Item>>::add_stream(fut, self)
}
/// Registers a stream with the context, ignoring errors.
///
/// This method is similar to `add_stream` but it skips stream
/// errors.
///
/// ```
/// use actix::prelude::*;
/// use futures_util::stream::once;
///
/// #[derive(Message)]
/// #[rtype(result = "()")]
/// struct Ping;
///
/// struct MyActor;
///
/// impl Handler<Ping> for MyActor {
/// type Result = ();
///
/// fn handle(&mut self, msg: Ping, ctx: &mut Context<MyActor>) {
/// println!("PING");
/// # System::current().stop();
/// }
/// }
///
/// impl Actor for MyActor {
/// type Context = Context<Self>;
///
/// fn started(&mut self, ctx: &mut Context<Self>) {
/// // add messages stream
/// ctx.add_message_stream(once(async { Ping }));
/// }
/// }
///
/// # #[actix::main] async fn main () {
/// let addr = MyActor.start();
/// # System::current().stop(); }
/// ```
fn add_message_stream<S>(&mut self, fut: S)
where
S: Stream + 'static,
S::Item: Message,
A: Handler<S::Item>,
{
if self.state() == ActorState::Stopped {
error!("Context::add_message_stream called for stopped actor.");
} else {
self.spawn(ActorMessageStreamItem::new(fut));
}
}
/// Sends the message `msg` to self. This bypasses the mailbox capacity, and
/// will always queue the message. If the actor is in the `stopped` state, an
/// error will be raised.
fn notify<M>(&mut self, msg: M)
where
A: Handler<M>,
M: Message + 'static,
{
if self.state() == ActorState::Stopped {
error!("Context::notify called for stopped actor.");
} else {
self.spawn(ActorMessageItem::new(msg));
}
}
/// Sends the message `msg` to self after a specified period of time.
///
/// Returns a spawn handle which can be used for cancellation. The
/// notification gets cancelled if the context's stop method gets
/// called. This bypasses the mailbox capacity, and
/// will always queue the message. If the actor is in the `stopped` state, an
/// error will be raised.
fn notify_later<M>(&mut self, msg: M, after: Duration) -> SpawnHandle
where
A: Handler<M>,
M: Message + 'static,
{
if self.state() == ActorState::Stopped {
error!("Context::notify_later called for stopped actor.");
SpawnHandle::default()
} else {
self.spawn(ActorDelayedMessageItem::new(msg, after))
}
}
/// Executes a closure after a specified period of time.
///
/// The closure gets passed the same actor and its
/// context. Execution gets cancelled if the context's stop method
/// gets called.
fn run_later<F>(&mut self, dur: Duration, f: F) -> SpawnHandle
where
F: FnOnce(&mut A, &mut A::Context) + 'static,
{
self.spawn(TimerFunc::new(dur, f))
}
/// Spawns a job to execute the given closure periodically, at a
/// specified fixed interval.
fn run_interval<F>(&mut self, dur: Duration, f: F) -> SpawnHandle
where
F: FnMut(&mut A, &mut A::Context) + 'static,
{
self.spawn(IntervalFunc::new(dur, f).finish())
}
/// Spawns a periodic `task` function to begin executing at the given `start` time, and with the
/// given `interval` duration.
fn run_interval_at<F>(
&mut self,
start: tokio::time::Instant,
interval: Duration,
task: F,
) -> SpawnHandle
where
F: FnMut(&mut A, &mut A::Context) + 'static,
{
self.spawn(IntervalFunc::new_at(start, interval, task).finish())
}
}
/// A handle to a spawned future.
///
/// Can be used to cancel the future.
#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, Hash)]
pub struct SpawnHandle(usize);
impl SpawnHandle {
/// Gets the next handle.
pub fn next(self) -> SpawnHandle {
SpawnHandle(self.0 + 1)
}
#[doc(hidden)]
pub fn into_usize(self) -> usize {
self.0
}
}
================================================
FILE: actix/src/actors/mocker.rs
================================================
//! Mocking utility actor.
//!
//! This actor wraps any actor, and replaces instances of that actor with
//! mocker actor, which is able to accept all messages which the actor can
//! receive.
//!
//! Mocking is intended to be achieved by using a pattern similar to
//! ```ignore
//! #[cfg(not(test))]
//! type DBClientAct = DBClientActor;
//! #[cfg(test)]
//! type DBClientAct = Mocker<DBClientActor>;
//! ```
//! Then, the actor should be used as a system service (or arbiter service, but
//! take care that all the places which will use the mocked actor are on the
//! same arbiter). Thus, in a test, it will retrieve the mocker from the
//! registry instead of the actual actor.
//!
//! To set the mock function in the actor, the `init_actor` function
//! is used, which allows the state of an actor to be set when it is
//! started as an arbiter or system service. A closure which takes
//! `Box<Any>` is evaluated for every message, and must return
//! `Box<Any>`, specifically the return type for the message type
//! send.
//!
//! See the mock example to see how it can be used.
use std::{any::Any, marker::PhantomData};
use crate::{handler::MessageResponse, prelude::*};
/// This actor is able to wrap another actor and accept all the messages the
/// wrapped actor can, passing it to a closure which can mock the response of
/// the actor.
#[allow(clippy::type_complexity)]
pub struct Mocker<T: Sized + Unpin + 'static> {
phantom: PhantomData<T>,
mock: Box<dyn FnMut(Box<dyn Any>, &mut Context<Mocker<T>>) -> Box<dyn Any>>,
}
impl<T: Unpin> Mocker<T> {
#[allow(clippy::type_complexity)]
pub fn mock(
mock: Box<dyn FnMut(Box<dyn Any>, &mut Context<Mocker<T>>) -> Box<dyn Any>>,
) -> Mocker<T> {
Mocker::<T> {
phantom: PhantomData,
mock,
}
}
}
impl<T: SystemService> SystemService for Mocker<T> {}
impl<T: ArbiterService> ArbiterService for Mocker<T> {}
impl<T: Unpin> Supervised for Mocker<T> {}
impl<T: Unpin> Default for Mocker<T> {
fn default() -> Self {
panic!("Mocker actor used before set")
}
}
impl<T: Sized + Unpin + 'static> Actor for Mocker<T> {
type Context = Context<Self>;
}
impl<M: 'static, T: Sized + Unpin + 'static> Handler<M> for Mocker<T>
where
M: Message,
<M as Message>::Result: MessageResponse<Mocker<T>, M>,
{
type Result = M::Result;
fn handle(&mut self, msg: M, ctx: &mut Self::Context) -> M::Result {
let mut ret = (self.mock)(Box::new(msg), ctx);
let out = ret
.downcast_mut::<Option<M::Result>>()
.expect("wrong return type for message")
.take();
match out {
Some(a) => a,
_ => panic!(),
}
}
}
================================================
FILE: actix/src/actors/mod.rs
================================================
//! Helper actors
pub mod mocker;
================================================
FILE: actix/src/address/channel.rs
================================================
//! This is copy of [sync/mpsc/](https://github.com/rust-lang/futures-rs)
use std::{
fmt,
hash::{Hash, Hasher},
pin::Pin,
sync::{
atomic::{
AtomicBool, AtomicUsize,
Ordering::{Relaxed, SeqCst},
},
Arc, Weak,
},
task::{self, Poll},
thread,
};
use futures_core::{stream::Stream, task::__internal::AtomicWaker};
use parking_lot::Mutex;
use tokio::sync::oneshot::{channel as oneshot_channel, Receiver as OneshotReceiver};
use super::{
envelope::{Envelope, ToEnvelope},
queue::Queue,
SendError,
};
use crate::{
actor::Actor,
handler::{Handler, Message},
};
pub trait Sender<M>: Send
where
M::Result: Send,
M: Message + Send,
{
fn do_send(&self, msg: M) -> Result<(), SendError<M>>;
fn try_send(&self, msg: M) -> Result<(), SendError<M>>;
fn send(&self, msg: M) -> Result<OneshotReceiver<M::Result>, SendError<M>>;
fn boxed(&self) -> Box<dyn Sender<M> + Sync>;
fn hash(&self) -> usize;
fn connected(&self) -> bool;
/// Returns a downgraded sender, where the sender is downgraded into its weak counterpart.
fn downgrade(&self) -> Box<dyn WeakSender<M> + Sync + 'static>;
}
impl<S, M> Sender<M> for Box<S>
where
S: Sender<M> + ?Sized,
M::Result: Send,
M: Message + Send,
{
fn do_send(&self, msg: M) -> Result<(), SendError<M>> {
(**self).do_send(msg)
}
fn try_send(&self, msg: M) -> Result<(), SendError<M>> {
(**self).try_send(msg)
}
fn send(&self, msg: M) -> Result<OneshotReceiver<<M as Message>::Result>, SendError<M>> {
(**self).send(msg)
}
fn boxed(&self) -> Box<dyn Sender<M> + Sync> {
(**self).boxed()
}
fn hash(&self) -> usize {
(**self).hash()
}
fn connected(&self) -> bool {
(**self).connected()
}
fn downgrade(&self) -> Box<dyn WeakSender<M> + Sync> {
(**self).downgrade()
}
}
pub trait WeakSender<M>: Send
where
M::Result: Send,
M: Message + Send,
{
/// Attempts to upgrade a `WeakAddressSender<A>` to a [`Sender<M>`]
///
/// Returns [`None`] if the actor has since been dropped.
fn upgrade(&self) -> Option<Box<dyn Sender<M> + Sync>>;
fn boxed(&self) -> Box<dyn WeakSender<M> + Sync>;
}
/// The transmission end of a channel which is used to send values.
///
/// This is created by the `channel` method.
pub struct AddressSender<A: Actor> {
// Channel state shared between the sender and receiver.
inner: Arc<Inner<A>>,
// Handle to the task that is blocked on this sender. This handle is sent
// to the receiver half in order to be notified when the sender becomes
// unblocked.
sender_task: Arc<Mutex<SenderTask>>,
// True if the sender might be blocked. This is an optimization to avoid
// having to lock the mutex most of the time.
maybe_parked: Arc<AtomicBool>,
}
impl<A: Actor> fmt::Debug for AddressSender<A> {
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt.debug_struct("AddressSender")
.field("sender_task", &self.sender_task)
.field("maybe_parked", &self.maybe_parked)
.finish()
}
}
/// A weakly referenced version of `AddressSender`.
///
/// This is created by the `AddressSender::downgrade` method.
pub struct WeakAddressSender<A: Actor> {
inner: Weak<Inner<A>>,
}
impl<A: Actor> Clone for WeakAddressSender<A> {
fn clone(&self) -> WeakAddressSender<A> {
WeakAddressSender {
inner: self.inner.clone(),
}
}
}
impl<A: Actor> fmt::Debug for WeakAddressSender<A> {
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt.debug_struct("WeakAddressSender").finish()
}
}
impl<A: Actor> PartialEq for WeakAddressSender<A> {
fn eq(&self, other: &Self) -> bool {
self.inner.ptr_eq(&other.inner)
}
}
impl<A: Actor> Eq for WeakAddressSender<A> {}
#[allow(dead_code)]
trait AssertKinds: Send + Sync + Clone {}
/// The receiving end of a channel which implements the `Stream` trait.
///
/// This is a concrete implementation of a stream which can be used to represent
/// a stream of values being computed elsewhere. This is created by the
/// `channel` method.
pub struct AddressReceiver<A: Actor> {
inner: Arc<Inner<A>>,
}
/// Generate `AddressSenders` for the channel
pub struct AddressSenderProducer<A: Actor> {
inner: Arc<Inner<A>>,
}
struct Inner<A: Actor> {
// Max buffer size of the channel. If `0` then the channel is unbounded.
buffer: AtomicUsize,
// Internal channel state. Consists of the number of messages stored in the
// channel as well as a flag signalling that the channel is closed.
state: AtomicUsize,
// Atomic, FIFO queue used to send messages to the receiver.
message_queue: Queue<Envelope<A>>,
// Atomic, FIFO queue used to send parked task handles to the receiver.
parked_queue: Queue<Arc<Mutex<SenderTask>>>,
// Number of senders in existence.
num_senders: AtomicUsize,
// Handle to the receiver's task.
recv_task: AtomicWaker,
}
// Struct representation of `Inner::state`.
#[derive(Debug, Clone, Copy)]
struct State {
// `true` when the channel is open
is_open: bool,
// Number of messages in the channel
num_messages: usize,
}
impl State {
fn is_closed(&self) -> bool {
!self.is_open && self.num_messages == 0
}
}
// The `is_open` flag is stored in the left-most bit of `Inner::state`
const OPEN_MASK: usize = usize::MAX - (usize::MAX >> 1);
// When a new channel is created, it is created in the open state with no
// pending messages.
const INIT_STATE: usize = OPEN_MASK;
// The maximum number of messages that a channel can track is `usize::MAX >> 1`
const MAX_CAPACITY: usize = !(OPEN_MASK);
// The maximum requested buffer size must be less than the maximum capacity of
// a channel. This is because each sender gets a guaranteed slot.
const MAX_BUFFER: usize = MAX_CAPACITY >> 1;
// Sent to the consumer to wake up blocked producers
#[derive(Debug)]
struct SenderTask {
task: Option<task::Waker>,
is_parked: bool,
}
impl SenderTask {
fn new() -> Self {
SenderTask {
task: None,
is_parked: false,
}
}
fn notify(&mut self) -> bool {
self.is_parked = false;
if let Some(task) = self.task.take() {
task.wake();
true
} else {
false
}
}
}
/// Creates an in-memory channel implementation of the `Stream` trait with
/// bounded capacity.
///
/// This method creates a concrete implementation of the `Stream` trait which
/// can be used to send values across threads in a streaming fashion. This
/// channel is unique in that it implements back pressure to ensure that the
/// sender never outpaces the receiver. The channel capacity is equal to
/// `buffer + num-senders`. In other words, each sender gets a guaranteed slot
/// in the channel capacity, and on top of that there are `buffer` "first come,
/// first serve" slots available to all senders.
///
/// The `Receiver` returned implements the `Stream` trait and has access to any
/// number of the associated combinators for transforming the result.
pub fn channel<A: Actor>(buffer: usize) -> (AddressSender<A>, AddressReceiver<A>) {
// Check that the requested buffer size does not exceed the maximum buffer
// size permitted by the system.
assert!(buffer < MAX_BUFFER, "requested buffer size too large");
let inner = Arc::new(Inner {
buffer: AtomicUsize::new(buffer),
state: AtomicUsize::new(INIT_STATE),
message_queue: Queue::new(),
parked_queue: Queue::new(),
num_senders: AtomicUsize::new(1),
recv_task: AtomicWaker::new(),
});
let tx = AddressSender {
inner: Arc::clone(&inner),
sender_task: Arc::new(Mutex::new(SenderTask::new())),
maybe_parked: Arc::new(AtomicBool::new(false)),
};
let rx = AddressReceiver { inner };
(tx, rx)
}
//
//
// ===== impl Sender =====
//
//
impl<A: Actor> AddressSender<A> {
/// Is the channel still open
pub fn connected(&self) -> bool {
let curr = self.inner.state.load(SeqCst);
let state = decode_state(curr);
state.is_open
}
/// Attempts to send a message on this `Sender<A>` with blocking.
///
/// This function must be called from inside of a task.
pub fn send<M>(&self, msg: M) -> Result<OneshotReceiver<M::Result>, SendError<M>>
where
A: Handler<M>,
A::Context: ToEnvelope<A, M>,
M::Result: Send,
M: Message + Send,
{
// If the sender is currently blocked, reject the message
if !self.poll_unparked(false, None).is_ready() {
return Err(SendError::Full(msg));
}
// First, increment the number of messages contained by the channel.
// This operation will also atomically determine if the sender task
// should be parked.
//
// None is returned in the case that the channel has been closed by the
// receiver. This happens when `Receiver::close` is called or the
// receiver is dropped.
let park_self = match self.inc_num_messages() {
Some(num_messages) => {
// receiver is full
let buffer = self.inner.buffer.load(Relaxed);
buffer != 0 && num_messages >= buffer
}
None => return Err(SendError::Closed(msg)),
};
// If the channel has reached capacity, then the sender task needs to
// be parked. This will send the task handle on the parked task queue.
if park_self {
self.park();
}
let (tx, rx) = oneshot_channel();
let env = <A::Context as ToEnvelope<A, M>>::pack(msg, Some(tx));
self.queue_push_and_signal(env);
Ok(rx)
}
/// Attempts to send a message on this `Sender<A>` without blocking.
pub fn try_send<M>(&self, msg: M, park: bool) -> Result<(), SendError<M>>
where
A: Handler<M>,
<A as Actor>::Context: ToEnvelope<A, M>,
M::Result: Send,
M: Message + Send + 'static,
{
// If the sender is currently blocked, reject the message
if !self.poll_unparked(false, None).is_ready() {
return Err(SendError::Full(msg));
}
let park_self = match self.inc_num_messages() {
Some(num_messages) => {
// receiver is full
let buffer = self.inner.buffer.load(Relaxed);
buffer != 0 && num_messages >= buffer
}
None => return Err(SendError::Closed(msg)),
};
if park_self && park {
self.park();
}
let env = <A::Context as ToEnvelope<A, M>>::pack(msg, None);
self.queue_push_and_signal(env);
Ok(())
}
/// Send a message on this `Sender<A>` without blocking.
///
/// This function does not park current task.
pub fn do_send<M>(&self, msg: M) -> Result<(), SendError<M>>
where
A: Handler<M>,
<A as Actor>::Context: ToEnvelope<A, M>,
M::Result: Send,
M: Message + Send,
{
if self.inc_num_messages().is_none() {
Err(SendError::Closed(msg))
} else {
// If inc_num_messages returned Some(park_self), then the mailbox is still active.
// We ignore the boolean (indicating to park and wait) in the Some, and queue the
// message regardless.
let env = <A::Context as ToEnvelope<A, M>>::pack(msg, None);
self.queue_push_and_signal(env);
Ok(())
}
}
/// Downgrade to `WeakAddressSender` which can later be upgraded
pub fn downgrade(&self) -> WeakAddressSender<A> {
WeakAddressSender {
inner: Arc::downgrade(&self.inner),
}
}
// Push message to the queue and signal to the receiver
fn queue_push_and_signal(&self, msg: Envelope<A>) {
// Push the message onto the message queue
self.inner.message_queue.push(msg);
// Signal to the receiver that a message has been enqueued. If the
// receiver is parked, this will unpark the task.
self.inner.recv_task.wake();
}
// Increment the number of queued messages. Returns if the sender should
// block.
fn inc_num_messages(&self) -> Option<usize> {
let mut curr = self.inner.state.load(SeqCst);
loop {
let mut state = decode_state(curr);
if !state.is_open {
return None;
}
state.num_messages += 1;
let next = encode_state(&state);
match self
.inner
.state
.compare_exchange(curr, next, SeqCst, SeqCst)
{
Ok(_) => {
return Some(state.num_messages);
}
Err(actual) => curr = actual,
}
}
}
// TODO: Not sure about this one, I modified code to match the futures one, might still be buggy
fn park(&self) {
{
let mut sender = self.sender_task.lock();
sender.task = None;
sender.is_parked = true;
}
// Send handle over queue
self.inner.parked_queue.push(Arc::clone(&self.sender_task));
// Check to make sure we weren't closed after we sent our task on the queue
let state = decode_state(self.inner.state.load(SeqCst));
self.maybe_parked.store(state.is_open, Relaxed);
}
fn poll_unparked(&self, do_park: bool, cx: Option<&mut task::Context<'_>>) -> Poll<()> {
// First check the `maybe_parked` variable. This avoids acquiring the
// lock in most cases
if self.maybe_parked.load(Relaxed) {
// Get a lock on the task handle
let mut task = self.sender_task.lock();
if !task.is_parked {
self.maybe_parked.store(false, Relaxed);
return Poll::Ready(());
}
// At this point, an unpark request is pending, so there will be an
// unpark sometime in the future. We just need to make sure that
// the correct task will be notified.
//
// Update the task in case the `Sender` has been moved to another
// task
task.task = if do_park {
cx.map(|cx| cx.waker().clone())
} else {
None
};
Poll::Pending
} else {
Poll::Ready(())
}
}
}
impl<A, M> Sender<M> for AddressSender<A>
where
A: Handler<M>,
A::Context: ToEnvelope<A, M>,
M::Result: Send,
M: Message + Send + 'static,
{
fn do_send(&self, msg: M) -> Result<(), SendError<M>> {
self.do_send(msg)
}
fn try_send(&self, msg: M) -> Result<(), SendError<M>> {
self.try_send(msg, true)
}
fn send(&self, msg: M) -> Result<OneshotReceiver<M::Result>, SendError<M>> {
self.send(msg)
}
fn boxed(&self) -> Box<dyn Sender<M> + Sync> {
Box::new(self.clone())
}
fn hash(&self) -> usize {
let hash: *const _ = self.inner.as_ref();
hash as usize
}
fn connected(&self) -> bool {
self.connected()
}
fn downgrade(&self) -> Box<dyn WeakSender<M> + Sync + 'static> {
Box::new(WeakAddressSender {
inner: Arc::downgrade(&self.inner),
})
}
}
impl<A: Actor> Clone for AddressSender<A> {
fn clone(&self) -> AddressSender<A> {
// Since this atomic op isn't actually guarding any memory and we don't
// care about any orderings besides the ordering on the single atomic
// variable, a relaxed ordering is acceptable.
let mut curr = self.inner.num_senders.load(SeqCst);
loop {
// If the maximum number of senders has been reached, then fail
if curr == self.inner.max_senders() {
panic!("cannot clone `Sender` -- too many outstanding senders");
}
debug_assert!(curr < self.inner.max_senders());
let next = curr + 1;
#[allow(deprecated)]
let actual = self.inner.num_senders.compare_and_swap(curr, next, SeqCst);
// The ABA problem doesn't matter here. We only care that the
// number of senders never exceeds the maximum.
if actual == curr {
return AddressSender {
inner: Arc::clone(&self.inner),
sender_task: Arc::new(Mutex::new(SenderTask::new())),
maybe_parked: Arc::new(AtomicBool::new(false)),
};
}
curr = actual;
}
}
}
impl<A: Actor> Drop for AddressSender<A> {
fn drop(&mut self) {
// Ordering between variables don't matter here
let prev = self.inner.num_senders.fetch_sub(1, SeqCst);
// last sender, notify receiver task
if prev == 1 {
self.inner.recv_task.wake();
}
}
}
impl<A: Actor> PartialEq for AddressSender<A> {
fn eq(&self, other: &Self) -> bool {
Arc::ptr_eq(&self.inner, &other.inner)
}
}
impl<A: Actor> Eq for AddressSender<A> {}
impl<A: Actor> Hash for AddressSender<A> {
fn hash<H: Hasher>(&self, state: &mut H) {
let hash: *const Inner<A> = self.inner.as_ref();
hash.hash(state);
}
}
//
//
// ===== impl WeakSender =====
//
//
impl<A: Actor> WeakAddressSender<A> {
/// Attempts to upgrade the `WeakAddressSender<A>` pointer to an [`AddressSender<A>`]
///
/// Returns [`None`] if the actor has since been dropped.
pub fn upgrade(&self) -> Option<AddressSender<A>> {
Weak::upgrade(&self.inner).map(|inner| AddressSenderProducer { inner }.sender())
}
}
impl<A, M> WeakSender<M> for WeakAddressSender<A>
where
A: Handler<M>,
A::Context: ToEnvelope<A, M>,
M::Result: Send,
M: Message + Send + 'static,
{
fn upgrade(&self) -> Option<Box<dyn Sender<M> + Sync>> {
if let Some(inner) = WeakAddressSender::upgrade(self) {
Some(Box::new(inner))
} else {
None
}
}
fn boxed(&self) -> Box<dyn WeakSender<M> + Sync> {
Box::new(self.clone())
}
}
//
//
// ===== impl SenderProducer =====
//
//
impl<A: Actor> AddressSenderProducer<A> {
/// Are any senders connected
pub fn connected(&self) -> bool {
self.inner.num_senders.load(SeqCst) != 0
}
/// Get channel capacity
pub fn capacity(&self) -> usize {
self.inner.buffer.load(Relaxed)
}
/// Set channel capacity
///
/// This method wakes up all waiting senders if new capacity is greater
/// than current
pub fn set_capacity(&mut self, cap: usize) {
let buffer = self.inner.buffer.load(Relaxed);
self.inner.buffer.store(cap, Relaxed);
// wake up all
if cap > buffer {
while let Some(task) = unsafe { self.inner.parked_queue.pop_spin() } {
task.lock().notify();
}
}
}
/// Get sender side of the channel
pub fn sender(&self) -> AddressSender<A> {
// this code same as Sender::clone
let mut curr = self.inner.num_senders.load(SeqCst);
loop {
// If the maximum number of senders has been reached, then fail
if curr == self.inner.max_senders() {
panic!("cannot clone `Sender` -- too many outstanding senders");
}
let next = curr + 1;
#[allow(deprecated)]
let actual = self.inner.num_senders.compare_and_swap(curr, next, SeqCst);
// The ABA problem doesn't matter here. We only care that the
// number of senders never exceeds the maximum.
if actual == curr {
return AddressSender {
inner: Arc::clone(&self.inner),
sender_task: Arc::new(Mutex::new(SenderTask::new())),
maybe_parked: Arc::new(AtomicBool::new(false)),
};
}
curr = actual;
}
}
}
//
//
// ===== impl Receiver =====
//
//
impl<A: Actor> AddressReceiver<A> {
/// Returns whether any senders are still connected.
pub fn connected(&self) -> bool {
self.inner.num_senders.load(SeqCst) != 0
}
/// Returns the channel capacity.
pub fn capacity(&self) -> usize {
self.inner.buffer.load(Relaxed)
}
/// Sets the channel capacity.
///
/// This method wakes up all waiting senders if the new capacity
/// is greater than the current one.
pub fn set_capacity(&mut self, cap: usize) {
let buffer = self.inner.buffer.load(Relaxed);
self.inner.buffer.store(cap, Relaxed);
// wake up all
if cap > buffer {
while let Some(task) = unsafe { self.inner.parked_queue.pop_spin() } {
task.lock().notify();
}
}
}
/// Returns the sender side of the channel.
pub fn sender(&self) -> AddressSender<A> {
// this code same as Sender::clone
let mut curr = self.inner.num_senders.load(SeqCst);
loop {
// If the maximum number of senders has been reached, then fail
if curr == self.inner.max_senders() {
panic!("cannot clone `Sender` -- too many outstanding senders");
}
let next = curr + 1;
#[allow(deprecated)]
let actual = self.inner.num_senders.compare_and_swap(curr, next, SeqCst);
// The ABA problem doesn't matter here. We only care that the
// number of senders never exceeds the maximum.
if actual == curr {
return AddressSender {
inner: Arc::clone(&self.inner),
sender_task: Arc::new(Mutex::new(SenderTask::new())),
maybe_parked: Arc::new(AtomicBool::new(false)),
};
}
curr = actual;
}
}
/// Creates the sender producer.
pub fn sender_producer(&self) -> AddressSenderProducer<A> {
AddressSenderProducer {
inner: self.inner.clone(),
}
}
fn next_message(&mut self) -> Poll<Option<Envelope<A>>> {
// Pop off a message
match unsafe { self.inner.message_queue.pop_spin() } {
Some(msg) => {
// If there are any parked task handles in the parked queue,
// pop one and unpark it.
self.unpark_one();
// Decrement number of messages
self.dec_num_messages();
Poll::Ready(Some(msg))
}
None => {
let state = decode_state(self.inner.state.load(SeqCst));
if state.is_closed() {
// If closed flag is set AND there are no pending messages
// it means end of stream
Poll::Ready(None)
} else {
// If queue is open, we need to return Pending
// to be woken up when new messages arrive.
// If queue is closed but num_messages is non-zero,
// it means that senders updated the state,
// but didn't put message to queue yet,
// so we need to park until sender unparks the task
// after queueing the message.
Poll::Pending
}
}
}
}
// Unpark a single task handle if there is one pending in the parked queue
fn unpark_one(&mut self) {
if let Some(task) = unsafe { self.inner.parked_queue.pop_spin() } {
task.lock().notify();
}
}
fn dec_num_messages(&self) {
// OPEN_MASK is highest bit, so it's unaffected by subtraction
// unless there's underflow, and we know there's no underflow
// because number of messages at this point is always > 0.
self.inner.state.fetch_sub(1, SeqCst);
}
}
impl<A: Actor> Stream for AddressReceiver<A> {
type Item = Envelope<A>;
fn poll_next(self: Pin<&mut Self>, cx: &mut task::Context<'_>) -> Poll<Option<Self::Item>> {
let this = self.get_mut();
match this.next_message() {
Poll::Ready(msg) => Poll::Ready(msg),
Poll::Pending => {
// There are no messages to read, in this case, park.
this.inner.recv_task.register(cx.waker());
// Check queue again after parking to prevent race condition:
// a message could be added to the queue after previous `next_message`
// before `register` call.
this.next_message()
}
}
}
}
impl<A: Actor> Drop for AddressReceiver<A> {
fn drop(&mut self) {
// close
self.inner.set_closed();
// Wake up any threads waiting as they'll see that we've closed the
// channel and will continue on their merry way.
while let Some(task) = unsafe { self.inner.parked_queue.pop_spin() } {
task.lock().notify();
}
// Drain the channel of all pending messages
loop {
match self.next_message() {
Poll::Ready(Some(_)) => {}
Poll::Ready(None) => break,
Poll::Pending => {
let state = decode_state(self.inner.state.load(SeqCst));
// If the channel is closed, then there is no need to park.
if state.is_closed() {
break;
}
// TODO: Spinning isn't ideal, it might be worth
// investigating using a condvar or some other strategy
// here. That said, if this case is hit, then another thread
// is about to push the value into the queue and this isn't
// the only spinlock in the impl right now.
thread::yield_now();
}
}
}
}
}
//
//
// ===== impl Inner =====
//
//
impl<A: Actor> Inner<A> {
// The return value is such that the total number of messages that can be
// enqueued into the channel will never exceed MAX_CAPACITY
fn max_senders(&self) -> usize {
MAX_CAPACITY - self.buffer.load(Relaxed)
}
// Clear `open` flag in the state, keep `num_messages` intact.
fn set_closed(&self) {
let curr = self.state.load(SeqCst);
if !decode_state(curr).is_open {
return;
}
self.state.fetch_and(!OPEN_MASK, SeqCst);
}
}
unsafe impl<A: Actor> Send for Inner<A> {}
unsafe impl<A: Actor> Sync for Inner<A> {}
//
//
// ===== Helpers =====
//
//
fn decode_state(num: usize) -> State {
State {
is_open: num & OPEN_MASK == OPEN_MASK,
num_messages: num & MAX_CAPACITY,
}
}
fn encode_state(state: &State) -> usize {
let mut num = state.num_messages;
if state.is_open {
num |= OPEN_MASK;
}
num
}
#[cfg(test)]
mod tests {
use std::time;
use super::*;
use crate::{address::queue::PopResult, prelude::*};
struct Act;
impl Actor for Act {
type Context = Context<Act>;
}
struct Ping;
impl Message for Ping {
type Result = ();
}
impl Handler<Ping> for Act {
type Result = ();
fn handle(&mut self, _: Ping, _: &mut Context<Act>) {}
}
#[test]
fn test_cap() {
System::new().block_on(async {
let (s1, mut recv) = channel::<Act>(1);
let s2 = recv.sender();
let arb = Arbiter::new();
arb.spawn_fn(move || {
let _ = s1.send(Ping);
});
thread::sleep(time::Duration::from_millis(100));
let arb2 = Arbiter::new();
arb2.spawn_fn(move || {
let _ = s2.send(Ping);
let _ = s2.send(Ping);
});
thread::sleep(time::Duration::from_millis(100));
let state = decode_state(recv.inner.state.load(SeqCst));
assert_eq!(state.num_messages, 2);
let p = loop {
match unsafe { recv.inner.parked_queue.pop() } {
PopResult::Data(task) => break Some(task),
PopResult::Empty => break None,
PopResult::Inconsistent => thread::yield_now(),
}
};
assert!(p.is_some());
recv.inner.parked_queue.push(p.unwrap());
recv.set_capacity(10);
thread::sleep(time::Duration::from_millis(100));
let state = decode_state(recv.inner.state.load(SeqCst));
assert_eq!(state.num_messages, 2);
let p = loop {
match unsafe { recv.inner.parked_queue.pop() } {
PopResult::Data(task) => break Some(task),
PopResult::Empty => break None,
PopResult::Inconsistent => thread::yield_now(),
}
};
assert!(p.is_none());
System::current().stop();
});
}
}
================================================
FILE: actix/src/address/envelope.rs
================================================
use tokio::sync::oneshot::Sender;
use crate::{
actor::{Actor, AsyncContext},
context::Context,
handler::{Handler, Message, MessageResponse},
};
/// Converter trait, packs message into a suitable envelope.
pub trait ToEnvelope<A, M: Message>
where
A: Actor + Handler<M>,
A::Context: ToEnvelope<A, M>,
{
/// Pack message into suitable envelope
fn pack(msg: M, tx: Option<Sender<M::Result>>) -> Envelope<A>;
}
pub trait EnvelopeProxy<A: Actor> {
/// handle message within new actor and context
fn handle(&mut self, act: &mut A, ctx: &mut A::Context);
}
impl<A, M> ToEnvelope<A, M> for Context<A>
where
A: Actor<Context = Context<A>> + Handler<M>,
M: Message + Send + 'static,
M::Result: Send,
{
fn pack(msg: M, tx: Option<Sender<M::Result>>) -> Envelope<A> {
Envelope::new(msg, tx)
}
}
pub struct Envelope<A: Actor>(Box<dyn EnvelopeProxy<A> + Send>);
impl<A: Actor> Envelope<A> {
pub fn new<M>(msg: M, tx: Option<Sender<M::Result>>) -> Self
where
A: Handler<M>,
A::Context: AsyncContext<A>,
M: Message + Send + 'static,
M::Result: Send,
{
Envelope(Box::new(SyncEnvelopeProxy { tx, msg: Some(msg) }))
}
pub fn with_proxy(proxy: Box<dyn EnvelopeProxy<A> + Send>) -> Self {
Envelope(proxy)
}
}
impl<A: Actor> EnvelopeProxy<A> for Envelope<A> {
fn handle(&mut self, act: &mut A, ctx: &mut <A as Actor>::Context) {
self.0.handle(act, ctx)
}
}
pub struct SyncEnvelopeProxy<M>
where
M: Message + Send,
M::Result: Send,
{
msg: Option<M>,
tx: Option<Sender<M::Result>>,
}
impl<A, M> EnvelopeProxy<A> for SyncEnvelopeProxy<M>
where
M: Message + Send + 'static,
M::Result: Send,
A: Actor + Handler<M>,
A::Context: AsyncContext<A>,
{
fn handle(&mut self, act: &mut A, ctx: &mut <A as Actor>::Context) {
let tx = self.tx.take();
if tx.is_some() && tx.as_ref().unwrap().is_closed() {
return;
}
if let Some(msg) = self.msg.take() {
let fut = <A as Handler<M>>::handle(act, msg, ctx);
fut.handle(ctx, tx)
}
}
}
================================================
FILE: actix/src/address/message.rs
================================================
use std::{
future::Future,
pin::Pin,
task::{self, Poll},
time::Duration,
};
use pin_project_lite::pin_project;
use tokio::sync::oneshot;
use super::{
channel::{AddressSender, Sender},
MailboxError, SendError,
};
use crate::{clock::Sleep, handler::Message};
pub type Request<A, M> = MsgRequest<AddressSender<A>, M>;
pub type RecipientRequest<M> = MsgRequest<Box<dyn Sender<M>>, M>;
pin_project! {
/// A `Future` which represents an asynchronous message sending process.
#[must_use = "You must wait on the request otherwise the Message will not be delivered"]
pub struct MsgRequest<S, M>
where
S: Sender<M>,
M: Message,
M: Send,
M::Result: Send
{
rx: Option<oneshot::Receiver<M::Result>>,
info: Option<(S, M)>,
#[pin]
timeout: Option<Sleep>,
}
}
impl<S, M> MsgRequest<S, M>
where
S: Sender<M>,
M: Message + Send,
M::Result: Send,
{
pub(crate) fn new(rx: Option<oneshot::Receiver<M::Result>>, info: Option<(S, M)>) -> Self {
Self {
rx,
info,
timeout: None,
}
}
#[cfg(test)]
pub(crate) fn rx_is_some(&self) -> bool {
self.rx.is_some()
}
/// Set message delivery timeout
pub fn timeout(mut self, dur: Duration) -> Self {
self.timeout = Some(actix_rt::time::sleep(dur));
self
}
}
impl<S, M> Future for MsgRequest<S, M>
where
S: Sender<M>,
M: Message + Send,
M::Result: Send,
{
type Output = Result<M::Result, MailboxError>;
fn poll(self: Pin<&mut Self>, cx: &mut task::Context<'_>) -> Poll<Self::Output> {
let this = self.project();
if let Some((sender, msg)) = this.info.take() {
match sender.send(msg) {
Ok(rx) => *this.rx = Some(rx),
Err(SendError::Full(msg)) => {
*this.info = Some((sender, msg));
return Poll::Pending;
}
Err(SendError::Closed(_)) => return Poll::Ready(Err(MailboxError::Closed)),
}
}
match this.rx {
Some(rx) => match Pin::new(rx).poll(cx) {
Poll::Ready(res) => Poll::Ready(res.map_err(|_| MailboxError::Closed)),
Poll::Pending => match this.timeout.as_pin_mut() {
Some(timeout) => timeout.poll(cx).map(|_| Err(MailboxError::Timeout)),
None => Poll::Pending,
},
},
None => Poll::Ready(Err(MailboxError::Closed)),
}
}
}
================================================
FILE: actix/src/address/mod.rs
================================================
use std::{
error, fmt,
hash::{Hash, Hasher},
};
pub(crate) mod channel;
mod envelope;
mod message;
mod queue;
pub(crate) use self::channel::{AddressReceiver, AddressSenderProducer};
use self::channel::{AddressSender, Sender, WeakAddressSender, WeakSender};
pub use self::{
envelope::{Envelope, EnvelopeProxy, ToEnvelope},
message::{RecipientRequest, Request},
};
use crate::{
actor::Actor,
handler::{Handler, Message},
};
pub enum SendError<T> {
Full(T),
Closed(T),
}
#[derive(Clone, Copy, PartialEq, Eq)]
/// The errors that can occur during the message delivery process.
pub enum MailboxError {
Closed,
Timeout,
}
impl fmt::Debug for MailboxError {
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(fmt, "MailboxError({})", self)
}
}
impl fmt::Display for MailboxError {
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
MailboxError::Closed => write!(fmt, "Mailbox has closed"),
MailboxError::Timeout => write!(fmt, "Message delivery timed out"),
}
}
}
impl error::Error for MailboxError {}
impl<T> SendError<T> {
pub fn into_inner(self) -> T {
match self {
SendError::Full(msg) | SendError::Closed(msg) => msg,
}
}
}
impl<T> error::Error for SendError<T> {}
impl<T> fmt::Debug for SendError<T> {
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
match *self {
SendError::Full(_) => write!(fmt, "SendError::Full(..)"),
SendError::Closed(_) => write!(fmt, "SendError::Closed(..)"),
}
}
}
impl<T> fmt::Display for SendError<T> {
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
match *self {
SendError::Full(_) => write!(fmt, "send failed because receiver is full"),
SendError::Closed(_) => write!(fmt, "send failed because receiver is gone"),
}
}
}
/// The address of an actor.
pub struct Addr<A: Actor> {
tx: AddressSender<A>,
}
impl<A: Actor> Addr<A> {
pub fn new(tx: AddressSender<A>) -> Addr<A> {
Addr { tx }
}
/// Returns whether the actor is still alive.
#[inline]
pub fn connected(&self) -> bool {
self.tx.connected()
}
/// Sends a message unconditionally, ignoring any potential errors.
///
/// The message is always queued, even if the mailbox for the receiver is full. If the mailbox
/// is closed, the message is silently dropped.
#[inline]
pub fn do_send<M>(&self, msg: M)
where
M: Message + Send,
M::Result: Send,
A: Handler<M>,
A::Context: ToEnvelope<A, M>,
{
let _ = self.tx.do_send(msg);
}
/// Tries to send a message.
///
/// This method fails if actor's mailbox is full or closed. This
/// method registers the current task in the receiver's queue.
pub fn try_send<M>(&self, msg: M) -> Result<(), SendError<M>>
where
M: Message + Send + 'static,
M::Result: Send,
A: Handler<M>,
A::Context: ToEnvelope<A, M>,
{
self.tx.try_send(msg, true)
}
/// Sends an asynchronous message and waits for a response.
///
/// The communication channel to the actor is bounded. If the returned request future gets
/// dropped, the message is cancelled.
#[inline]
pub fn send<M>(&self, msg: M) -> Request<A, M>
where
M: Message + Send + 'static,
M::Result: Send,
A: Handler<M>,
A::Context: ToEnvelope<A, M>,
{
match self.tx.send(msg) {
Ok(rx) => Request::new(Some(rx), None),
Err(SendError::Full(msg)) => Request::new(None, Some((self.tx.clone(), msg))),
Err(SendError::Closed(_)) => Request::new(None, None),
}
}
/// Returns the [`Recipient`] for a specific message type.
pub fn recipient<M>(self) -> Recipient<M>
where
A: Handler<M>,
A::Context: ToEnvelope<A, M>,
M: Message + Send + 'static,
M::Result: Send,
{
self.into()
}
/// Returns a downgraded [`WeakAddr`].
pub fn downgrade(&self) -> WeakAddr<A> {
WeakAddr {
wtx: self.tx.downgrade(),
}
}
}
impl<A: Actor> Clone for Addr<A> {
fn clone(&self) -> Addr<A> {
Addr {
tx: self.tx.clone(),
}
}
}
impl<A: Actor> PartialEq for Addr<A> {
fn eq(&self, other: &Self) -> bool {
self.tx == other.tx
}
}
impl<A: Actor> Eq for Addr<A> {}
impl<A: Actor> Hash for Addr<A> {
fn hash<H: Hasher>(&self, state: &mut H) {
self.tx.hash(state)
}
}
impl<A: Actor> fmt::Debug for Addr<A> {
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt.debug_struct("Addr").field("tx", &self.tx).finish()
}
}
/// A weakly referenced counterpart to `Addr<A>`.
pub struct WeakAddr<A: Actor> {
wtx: WeakAddressSender<A>,
}
impl<A: Actor> WeakAddr<A> {
/// Attempts to upgrade the [`WeakAddr<A>`] pointer to an [`Addr<A>`].
///
/// Returns `None` if the actor has since been dropped or the
/// underlying address is disconnected.
pub fn upgrade(&self) -> Option<Addr<A>> {
match self.wtx.upgrade() {
Some(tx) => {
if tx.connected() {
Some(Addr::new(tx))
} else {
None
}
}
None => None,
}
}
pub fn recipient<M>(self) -> WeakRecipient<M>
where
A: Handler<M>,
A::Context: ToEnvelope<A, M>,
M: Message + Send + 'static,
M::Result: Send,
{
self.into()
}
}
impl<A: Actor> Clone for WeakAddr<A> {
fn clone(&self) -> WeakAddr<A> {
WeakAddr {
wtx: self.wtx.clone(),
}
}
}
impl<A: Actor> fmt::Debug for WeakAddr<A> {
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt.debug_struct("WeakAddr")
.field("wtx", &self.wtx)
.finish()
}
}
impl<A: Actor> PartialEq for WeakAddr<A> {
fn eq(&self, other: &Self) -> bool {
self.wtx == other.wtx
}
}
impl<A: Actor> std::cmp::Eq for WeakAddr<A> {}
/// The [`Recipient`] type allows to send one specific message to an actor.
///
/// You can get a recipient using the `Addr::recipient()` method. It is possible
/// to use the `Clone::clone()` method to get a cloned recipient.
pub struct Recipient<M: Message>
where
M: Message + Send,
M::Result: Send,
{
tx: Box<dyn Sender<M> + Sync>,
}
impl<M> Recipient<M>
where
M: Message + Send,
M::Result: Send,
{
/// Creates a new recipient.
pub(crate) fn new(tx: Box<dyn Sender<M> + Sync>) -> Recipient<M> {
Recipient { tx }
}
/// Sends a message.
///
/// The message is always queued, even if the mailbox for the receiver is full. If the mailbox
/// is closed, the message is silently dropped.
pub fn do_send(&self, msg: M) {
let _ = self.tx.do_send(msg);
}
/// Attempts to send a message.
///
/// This method fails if the actor's mailbox is full or closed. This method registers the
/// current task in the receivers queue.
pub fn try_send(&self, msg: M) -> Result<(), SendError<M>> {
self.tx.try_send(msg)
}
/// Sends a message and asynchronously wait for a response.
///
/// The communication channel to the actor is bounded. If the returned `RecipientRequest` object
/// gets dropped, the message is cancelled.
pub fn send(&self, msg: M) -> RecipientRequest<M> {
match self.tx.send(msg) {
Ok(rx) => RecipientRequest::new(Some(rx), None),
Err(SendError::Full(msg)) => RecipientRequest::new(None, Some((self.tx.boxed(), msg))),
Err(SendError::Closed(_)) => RecipientRequest::new(None, None),
}
}
pub fn connected(&self) -> bool {
self.tx.connected()
}
/// Returns a downgraded `WeakRecipient`
pub fn downgrade(&self) -> WeakRecipient<M> {
WeakRecipient {
wtx: self.tx.downgrade(),
}
}
}
impl<A: Actor, M: Message + Send + 'static> From<Addr<A>> for Recipient<M>
where
A: Handler<M>,
M::Result: Send,
A::Context: ToEnvelope<A, M>,
{
fn from(addr: Addr<A>) -> Self {
Recipient::new(Box::new(addr.tx))
}
}
impl<M> Clone for Recipient<M>
where
M: Message + Send,
M::Result: Send,
{
fn clone(&self) -> Recipient<M> {
Recipient {
tx: self.tx.boxed(),
}
}
}
impl<M> PartialEq for Recipient<M>
where
M: Message + Send,
M::Result: Send,
{
fn eq(&self, other: &Self) -> bool {
self.tx.hash() == other.tx.hash()
}
}
impl<M> Eq for Recipient<M>
where
M: Message + Send,
M::Result: Send,
{
}
impl<M> Hash for Recipient<M>
where
M: Message + Send,
M::Result: Send,
{
fn hash<H: Hasher>(&self, state: &mut H) {
self.tx.hash().hash(state)
}
}
impl<M> fmt::Debug for Recipient<M>
where
M: Message + Send,
M::Result: Send,
{
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(fmt, "Recipient {{ /* omitted */ }}")
}
}
/// A weakly referenced counterpart to `Recipient<M>`
pub struct WeakRecipient<M: Message>
where
M: Message + Send,
M::Result: Send,
{
wtx: Box<dyn WeakSender<M> + Sync>,
}
impl<M> fmt::Debug for WeakRecipient<M>
where
M: Message + Send,
M::Result: Send,
{
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(fmt, "WeakRecipient {{ /* omitted */ }}")
}
}
impl<M> Clone for WeakRecipient<M>
where
M: Message + Send,
M::Result: Send,
{
fn clone(&self) -> Self {
Self {
wtx: self.wtx.boxed(),
}
}
}
impl<M> From<Recipient<M>> for WeakRecipient<M>
where
M: Message + Send,
M::Result: Send,
{
fn from(recipient: Recipient<M>) -> Self {
recipient.downgrade()
}
}
impl<M> WeakRecipient<M>
where
M: Message + Send,
M::Result: Send,
{
pub(crate) fn new(wtx: Box<dyn WeakSender<M> + Sync>) -> WeakRecipient<M> {
WeakRecipient { wtx }
}
/// Attempts to upgrade the `WeakRecipient<M>` pointer to an `Recipient<M>`, similar to `WeakAddr<A>`
pub fn upgrade(&self) -> Option<Recipient<M>> {
self.wtx.upgrade().map(Recipient::new)
}
}
impl<A: Actor, M: Message + Send + 'static> From<Addr<A>> for WeakRecipient<M>
where
A: Handler<M>,
M::Result: Send,
A::Context: ToEnvelope<A, M>,
{
fn from(addr: Addr<A>) -> WeakRecipient<M> {
addr.downgrade().recipient()
}
}
impl<A: Actor, M: Message + Send + 'static> From<WeakAddr<A>> for WeakRecipient<M>
where
A: Handler<M>,
M::Result: Send,
A::Context: ToEnvelope<A, M>,
{
fn from(addr: WeakAddr<A>) -> WeakRecipient<M> {
WeakRecipient::new(Box::new(addr.wtx))
}
}
#[cfg(test)]
mod tests {
use std::sync::{
atomic::{AtomicUsize, Ordering},
Arc,
};
use crate::prelude::*;
struct ActorWithSmallMailBox(Arc<AtomicUsize>);
impl Actor for ActorWithSmallMailBox {
type Context = Context<Self>;
fn started(&mut self, ctx: &mut Self::Context) {
ctx.set_mailbox_capacity(1);
}
}
pub struct SetCounter(usize);
impl Message for SetCounter {
type Result = ();
}
impl Handler<SetCounter> for ActorWithSmallMailBox {
type Result = <SetCounter as Message>::Result;
fn handle(&mut self, ping: SetCounter, _: &mut Context<Self>) -> Self::Result {
self.0.store(ping.0, Ordering::Relaxed)
}
}
#[test]
fn test_send_over_limit() {
let count = Arc::new(AtomicUsize::new(0));
let count2 = Arc::clone(&count);
let sys = System::new();
sys.block_on(async move {
//Actor::started gets called after we relinquish
//control to event loop so we just set it ourself.
let addr = ActorWithSmallMailBox::create(|ctx| {
ctx.set_mailbox_capacity(1);
ActorWithSmallMailBox(count2)
});
let fut = async move {
let send = addr.clone().send(SetCounter(1));
assert!(send.rx_is_some());
let addr2 = addr.clone();
let send2 = addr2.send(SetCounter(2));
assert!(send2.rx_is_some());
let send3 = addr2.send(SetCounter(3));
assert!(!send3.rx_is_some());
let _ = send.await;
let _ = send2.await;
let _ = send3.await;
System::current().stop();
};
actix_rt::spawn(fut);
});
// run til system stop
sys.run().unwrap();
assert_eq!(count.load(Ordering::Relaxed), 3);
}
}
================================================
FILE: actix/src/address/queue.rs
================================================
/* Copyright (c) 2010-2011 Dmitry Vyukov. All rights reserved.
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY DMITRY VYUKOV "AS IS" AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
* SHALL DMITRY VYUKOV OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* The views and conclusions contained in the software and documentation are
* those of the authors and should not be interpreted as representing official
* policies, either expressed or implied, of Dmitry Vyukov.
*/
//! A mostly lock-free multi-producer, single consumer queue for sending
//! messages between asynchronous tasks.
//!
//! The queue implementation is essentially the same one used for mpsc channels
//! in the standard library.
//!
//! Note that the current implementation of this queue has a caveat of the `pop`
//! method, and see the method for more information about it. Due to this
//! caveat, this queue may not be appropriate for all use-cases.
// http://www.1024cores.net/home/lock-free-algorithms
// /queues/non-intrusive-mpsc-node-based-queue
// NOTE: this implementation is lifted from the standard library and only
// slightly modified
use std::{
cell::UnsafeCell,
ptr,
sync::atomic::{AtomicPtr, Ordering},
thread,
};
pub(super) use self::PopResult::*;
/// A result of the `pop` function.
pub(super) enum PopResult<T> {
/// Some data has been popped
Data(T),
/// The queue is empty
Empty,
/// The queue is in an inconsistent state. Popping data should succeed, but
/// some pushers have yet to make enough progress in order allow a pop to
/// succeed. It is recommended that a pop() occur "in the near future" in
/// order to see if the sender has made progress or not
Inconsistent,
}
#[derive(Debug)]
struct Node<T> {
next: AtomicPtr<Self>,
value: Option<T>,
}
/// The multi-producer single-consumer structure. This is not cloneable, but it
/// may be safely shared so long as it is guaranteed that there is only one
/// popper at a time (many pushers are allowed).
#[derive(Debug)]
pub(super) struct Queue<T> {
head: AtomicPtr<Node<T>>,
tail: UnsafeCell<*mut Node<T>>,
}
unsafe impl<T: Send> Send for Queue<T> {}
unsafe impl<T: Send> Sync for Queue<T> {}
impl<T> Node<T> {
unsafe fn new(v: Option<T>) -> *mut Self {
Box::into_raw(Box::new(Self {
next: AtomicPtr::new(ptr::null_mut()),
value: v,
}))
}
}
impl<T> Queue<T> {
/// Creates a new queue that is safe to share among multiple producers and
/// one consumer.
pub(super) fn new() -> Self {
let stub = unsafe { Node::new(None) };
Self {
head: AtomicPtr::new(stub),
tail: UnsafeCell::new(stub),
}
}
/// Pushes a new value onto this queue.
pub(super) fn push(&self, t: T) {
unsafe {
let n = Node::new(Some(t));
let prev = self.head.swap(n, Ordering::AcqRel);
(*prev).next.store(n, Ordering::Release);
}
}
/// Pops some data from this queue.
///
/// Note that the current implementation means that this function cannot
/// return `Option<T>`. It is possible for this queue to be in an
/// inconsistent state where many pushes have succeeded and completely
/// finished, but pops cannot return `Some(t)`. This inconsistent state
/// happens when a pusher is preempted at an inopportune moment.
///
/// This inconsistent state means that this queue does indeed have data, but
/// it does not currently have access to it at this time.
///
/// This function is unsafe because only one thread can call it at a time.
pub(super) unsafe fn pop(&self) -> PopResult<T> {
let tail = *self.tail.get();
let next = (*tail).next.load(Ordering::Acquire);
if !next.is_null() {
*self.tail.get() = next;
assert!((*tail).value.is_none());
assert!((*next).value.is_some());
let ret = (*next).value.take().unwrap();
drop(Box::from_raw(tail));
return Data(ret);
}
if ptr::eq(self.head.load(Ordering::Acquire), tail) {
Empty
} else {
Inconsistent
}
}
/// Pop an element similarly to `pop` function, but spin-wait on inconsistent
/// queue state instead of returning `Inconsistent`.
///
/// This function is unsafe because only one thread can call it at a time.
pub(super) unsafe fn pop_spin(&self) -> Option<T> {
loop {
match self.pop() {
Empty => return None,
Data(t) => return Some(t),
// Inconsistent means that there will be a message to pop
// in a short time. This branch can only be reached if
// values are being produced from another thread, so there
// are a few ways that we can deal with this:
//
// 1) Spin
// 2) thread::yield_now()
// 3) task::current().unwrap() & return Pending
//
// For now, thread::yield_now() is used, but it would
// probably be better to spin a few times then yield.
Inconsistent => {
thread::yield_now();
}
}
}
}
}
impl<T> Drop for Queue<T> {
fn drop(&mut self) {
unsafe {
let mut cur = *self.tail.get();
while !cur.is_null() {
let next = (*cur).next.load(Ordering::Relaxed);
drop(Box::from_raw(cur));
cur = next;
}
}
}
}
================================================
FILE: actix/src/clock.rs
================================================
//! Utilities for tracking time.
//!
//! This module provides a number of types for executing code after a set period of time.
//!
//! See [`tokio::time` module] for full documentation.
//!
//! [`tokio::time` module]: https://docs.rs/tokio/1.0.1/tokio/time/index.html
pub use actix_rt::time::*;
================================================
FILE: actix/src/context.rs
================================================
use std::fmt;
use crate::{
actor::{Actor, ActorContext, ActorState, AsyncContext, SpawnHandle},
address::{Addr, AddressReceiver},
context_impl::{AsyncContextParts, ContextFut, ContextParts},
fut::ActorFuture,
mailbox::Mailbox,
};
/// An actor execution context.
pub struct Context<A>
where
A: Actor<Context = Context<A>>,
{
parts: ContextParts<A>,
mb: Option<Mailbox<A>>,
}
impl<A: Actor<Context = Context<A>>> fmt::Debug for Context<A> {
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt.debug_struct("Context")
.field("parts", &self.parts)
.field("mb", &self.mb)
.finish()
}
}
impl<A> ActorContext for Context<A>
where
A: Actor<Context = Self>,
{
#[inline]
fn stop(&mut self) {
self.parts.stop()
}
#[inline]
fn terminate(&mut self) {
self.parts.terminate()
}
#[inline]
fn state(&self) -> ActorState {
self.parts.state()
}
}
impl<A> AsyncContext<A> for Context<A>
where
A: Actor<Context = Self>,
{
#[inline]
fn spawn<F>(&mut self, fut: F) -> SpawnHandle
where
F: ActorFuture<A, Output = ()> + 'static,
{
self.parts.spawn(fut)
}
#[inline]
fn wait<F>(&mut self, fut: F)
where
F: ActorFuture<A, Output = ()> + 'static,
{
self.parts.wait(fut)
}
#[inline]
fn waiting(&self) -> bool {
self.parts.waiting()
}
#[inline]
fn cancel_future(&mut self, handle: SpawnHandle) -> bool {
self.parts.cancel_future(handle)
}
#[inline]
fn address(&self) -> Addr<A> {
self.parts.address()
}
}
impl<A> Context<A>
where
A: Actor<Context = Self>,
{
/// Create a context without spawning it.
///
/// The context can be spawned into an actor using its [`run`](`Context::run`) method.
///
/// ```
/// # use actix::prelude::*;
/// struct Actor1 {
/// actor2_addr: Addr<Actor2>,
/// }
/// # impl Actor for Actor1 {
/// # type Context = Context<Self>;
/// # }
///
/// struct Actor2 {
/// actor1_addr: Addr<Actor1>,
/// }
/// # impl Actor for Actor2 {
/// # type Context = Context<Self>;
/// #
/// # fn started(&mut self, _: &mut Self::Context) {
/// # System::current().stop();
/// # }
/// # }
///
/// # fn main() {
/// # let sys = System::new();
/// # sys.block_on(async {
/// let ctx1 = Context::<Actor1>::new();
/// let ctx2 = Context::<Actor2>::new();
///
/// let actor1 = Actor1 { actor2_addr: ctx2.address() };
/// let actor2 = Actor2 { actor1_addr: ctx1.address() };
///
/// ctx1.run(actor1);
/// ctx2.run(actor2);
/// # });
/// # sys.run().unwrap();
/// # }
/// ```
#[inline]
pub fn new() -> Self {
let mb = Mailbox::default();
Self {
parts: ContextParts::new(mb.sender_producer()),
mb: Some(mb),
}
}
#[inline]
pub fn with_receiver(rx: AddressReceiver<A>) -> Self {
let mb = Mailbox::new(rx);
Self {
parts: ContextParts::new(mb.sender_producer()),
mb: Some(mb),
}
}
#[inline]
pub fn run(self, act: A) -> Addr<A> {
let fut = self.into_future(act);
let addr = fut.address();
actix_rt::spawn(fut);
addr
}
pub fn into_future(mut self, act: A) -> ContextFut<A, Self> {
let mb = self.mb.take().unwrap();
ContextFut::new(self, act, mb)
}
/// Returns a handle to the running future.
///
/// This is the handle returned by the `AsyncContext::spawn()`
/// method.
pub fn handle(&self) -> SpawnHandle {
self.parts.curr_handle()
}
/// Sets the mailbox capacity.
///
/// The default mailbox capacity is 16 messages.
/// #Examples
/// ```
/// # use actix::prelude::*;
/// struct MyActor;
/// impl Actor for MyActor {
/// type Context = Context<Self>;
///
/// fn started(&mut self, ctx: &mut Self::Context) {
/// ctx.set_mailbox_capacity(1);
/// System::current().stop();
/// }
/// }
///
/// # fn main() {
/// # let mut sys = System::new();
/// let addr = sys.block_on(async { MyActor.start() });
/// sys.run();
/// # }
/// ```
pub fn set_mailbox_capacity(&mut self, cap: usize) {
self.parts.set_mailbox_capacity(cap)
}
/// Returns whether any addresses are still connected.
pub fn connected(&self) -> bool {
self.parts.connected()
}
}
impl<A> Default for Context<A>
where
A: Actor<Context = Self>,
{
#[inline]
fn default() -> Self {
Self::new()
}
}
impl<A> AsyncContextParts<A> for Context<A>
where
A: Actor<Context = Self>,
{
fn parts(&mut self) -> &mut ContextParts<A> {
&mut self.parts
}
}
/// Helper trait which can spawn a future into the actor's context.
pub trait ContextFutureSpawner<A>
where
A: Actor,
A::Context: AsyncContext<A>,
{
/// Spawns the future into the given context.
fn spawn(self, ctx: &mut A::Context);
/// Spawns the future into the given context, waiting for it to
/// resolve.
///
/// This stops processing any incoming events until this future
/// resolves.
fn wait(self, ctx: &mut A::Context);
}
impl<A, T> ContextFutureSpawner<A> for T
where
A: Actor,
A::Context: AsyncContext<A>,
T: ActorFuture<A, Output = ()> + 'static,
{
#[inline]
fn spawn(self, ctx: &mut A::Context) {
let _ = ctx.spawn(self);
}
#[inline]
fn wait(self, ctx: &mut A::Context) {
ctx.wait(self);
}
}
================================================
FILE: actix/src/context_impl.rs
================================================
use std::{
fmt,
future::Future,
pin::Pin,
task::{Context, Poll},
};
use bitflags::bitflags;
use futures_core::ready;
use smallvec::SmallVec;
use crate::{
actor::{Actor, ActorContext, ActorState, AsyncContext, Running, SpawnHandle, Supervised},
address::{Addr, AddressSenderProducer},
context_items::ActorWaitItem,
fut::ActorFuture,
mailbox::Mailbox,
};
bitflags! {
/// Internal context state.
#[derive(Debug)]
struct ContextFlags: u8 {
const STARTED = 0b0000_0001;
const RUNNING = 0b0000_0010;
const STOPPING = 0b0000_0100;
const STOPPED = 0b0001_0000;
const MB_CAP_CHANGED = 0b0010_0000;
}
}
type Item<A> = (SpawnHandle, Pin<Box<dyn ActorFuture<A, Output = ()>>>);
pub trait AsyncContextParts<A>: ActorContext + AsyncContext<A>
where
A: Actor<Context = Self>,
{
fn parts(&mut self) -> &mut ContextParts<A>;
}
pub struct ContextParts<A>
where
A: Actor,
A::Context: AsyncContext<A>,
{
addr: AddressSenderProducer<A>,
flags: ContextFlags,
wait: SmallVec<[ActorWaitItem<A>; 2]>,
items: SmallVec<[Item<A>; 3]>,
handles: SmallVec<[SpawnHandle; 2]>,
}
impl<A> fmt::Debug for ContextParts<A>
where
A: Actor,
A::Context: AsyncContext<A>,
{
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt.debug_struct("ContextParts")
.field("flags", &self.flags)
.finish()
}
}
impl<A> ContextParts<A>
where
A: Actor,
A::Context: AsyncContext<A>,
{
#[inline]
/// Create new [`ContextParts`] instance
pub fn new(addr: AddressSenderProducer<A>) -> Self {
ContextParts {
addr,
flags: ContextFlags::RUNNING,
wait: SmallVec::new(),
items: SmallVec::new(),
handles: SmallVec::from_slice(&[SpawnHandle::default(), SpawnHandle::default()]),
}
}
#[inline]
/// Initiate stop process for actor execution
///
/// Actor could prevent stopping by returning `false` from
/// `Actor::stopping()` method.
pub fn stop(&mut self) {
if self.flags.contains(ContextFlags::RUNNING) {
self.flags.remove(ContextFlags::RUNNING);
self.flags.insert(ContextFlags::STOPPING);
}
}
#[inline]
/// Terminate actor execution
pub fn terminate(&mut self) {
self.flags = ContextFlags::STOPPED;
}
#[inline]
/// Actor execution state
pub fn state(&self) -> ActorState {
if self.flags.contains(ContextFlags::RUNNING) {
ActorState::Running
} else if self.flags.contains(ContextFlags::STOPPED) {
ActorState::Stopped
} else if self.flags.contains(ContextFlags::STOPPING) {
ActorState::Stopping
} else {
ActorState::Started
}
}
#[inline]
/// Is context waiting for future completion
pub fn waiting(&self) -> bool {
!self.wait.is_empty()
|| self
.flags
.intersects(ContextFlags::STOPPING | ContextFlags::STOPPED)
}
#[inline]
/// Handle of the running future
pub fn curr_handle(&self) -> SpawnHandle {
self.handles[1]
}
#[inline]
/// Spawn new future to this context.
pub fn spawn<F>(&mut self, fut: F) -> SpawnHandle
where
F: ActorFuture<A, Output = ()> + 'static,
{
let handle = self.handles[0].next();
self.handles[0] = handle;
let fut: Box<dyn ActorFuture<A, Output = ()>> = Box::new(fut);
self.items.push((handle, Pin::from(fut)));
handle
}
#[inline]
/// Spawn new future to this context and wait future completion.
///
/// During wait period actor does not receive any messages.
pub fn wait<F>(&mut self, f: F)
where
F: ActorFuture<A, Output = ()> + 'static,
{
self.wait.push(ActorWaitItem::new(f));
}
#[inline]
/// Cancel previously scheduled future.
pub fn cancel_future(&mut self, handle: SpawnHandle) -> bool {
self.handles.push(handle);
true
}
#[inline]
pub fn capacity(&mut self) -> usize {
self.addr.capacity()
}
#[inline]
pub fn set_mailbox_capacity(&mut self, cap: usize) {
self.flags.insert(ContextFlags::MB_CAP_CHANGED);
self.addr.set_capacity(cap);
}
#[inline]
pub fn address(&self) -> Addr<A> {
Addr::new(self.addr.sender())
}
/// Restarts this [`ContextParts`] by:
/// - canceling all the [`ActorFuture`]s spawned via [`ContextParts::spawn`];
/// - clearing the [`ContextParts::wait`] queue;
/// - changing the [`Actor`] state to [`ActorState::Running`].
#[inline]
pub(crate) fn restart(&mut self) {
self.flags = ContextFlags::RUNNING;
self.wait = SmallVec::new();
self.items = SmallVec::new();
self.handles[0] = SpawnHandle::default();
}
#[inline]
pub fn started(&mut self) -> bool {
self.flags.contains(ContextFlags::STARTED)
}
/// Are any senders connected
#[inline]
pub fn connected(&self) -> bool {
self.addr.connected()
}
}
pub struct ContextFut<A, C>
where
C: AsyncContextParts<A> + Unpin,
A: Actor<Context = C>,
{
ctx: C,
act: A,
mailbox: Mailbox<A>,
wait: SmallVec<[ActorWaitItem<A>; 2]>,
items: SmallVec<[Item<A>; 3]>,
}
impl<A, C> fmt::Debug for ContextFut<A, C>
where
C: AsyncContextParts<A> + Unpin,
A: Actor<Context = C>,
{
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(fmt, "ContextFut {{ /* omitted */ }}")
}
}
impl<A, C> Drop for ContextFut<A, C>
where
C: AsyncContextParts<A> + Unpin,
A: Actor<Context = C>,
{
fn drop(&mut self) {
if self.alive() {
self.ctx.parts().stop();
let waker = futures_task::noop_waker();
let mut cx = std::task::Context::from_waker(&waker);
let _ = Pin::new(self).poll(&mut cx);
}
}
}
impl<A, C> ContextFut<A, C>
where
C: AsyncContextParts<A> + Unpin,
A: Actor<Context = C>,
{
pub fn new(ctx: C, act: A, mailbox: Mailbox<A>) -> Self {
ContextFut {
ctx,
act,
mailbox,
wait: SmallVec::new(),
items: SmallVec::new(),
}
}
#[inline]
pub fn ctx(&mut self) -> &mut C {
&mut self.ctx
}
#[inline]
pub fn address(&self) -> Addr<A> {
self.mailbox.address()
}
#[inline]
fn stopping(&mut self) -> bool {
self.ctx
.parts()
.flags
.intersects(ContextFlags::STOPPING | ContextFlags::STOPPED)
}
#[inline]
pub fn alive(&mut self) -> bool {
if self.ctx.parts().flags.contains(ContextFlags::STOPPED) {
false
} else {
!self.ctx.parts().flags.contains(ContextFlags::STARTED)
|| self.mailbox.connected()
|| !self.items.is_empty()
|| !self.wait.is_empty()
}
}
/// Restarts the [`AsyncContext`] of this [`ContextFut`] returning whether the [`Context`] was
/// restarted.
///
/// Restarting the [`Context`] means:
/// - canceling all the [`ActorFuture`]s spawned by the [`AsyncContext`];
/// - clearing the [`ActorFuture`] await queue of the [`AsyncContext`];
/// - changing the [`Actor`] state to [`ActorState::Running`];
/// - calling [`Supervised::restarting`] on the [`Actor`].
///
/// Restart may fail only if the [`Mailbox`] is not [`connected`].
///
/// [`connected`]: Mailbox::connected
#[inline]
pub fn restart(&mut self) -> bool
where
A: Supervised,
{
if self.mailbox.connected() {
self.wait = SmallVec::new();
self.items = SmallVec::new();
self.ctx.parts().restart();
self.act.restarting(&mut self.ctx);
true
} else {
false
}
}
fn merge(&mut self) -> bool {
let mut modified = false;
let parts = self.ctx.parts();
if !parts.wait.is_empty() {
modified = true;
self.wait.extend(parts.wait.drain(0..));
}
if !parts.items.is_empty() {
modified = true;
self.items.extend(parts.items.drain(0..));
}
//
if parts.flags.contains(ContextFlags::MB_CAP_CHANGED) {
modified = true;
parts.flags.remove(ContextFlags::MB_CAP_CHANGED);
}
if parts.handles.len() > 2 {
modified = true;
}
modified
}
fn clean_canceled_handle(&mut self) {
fn remove_item_by_handle<C>(
items: &mut SmallVec<[Item<C>; 3]>,
handle: &SpawnHandle,
) -> bool {
let mut idx = 0;
let mut removed = false;
while idx < items.len() {
if &items[idx].0 == handle {
items.swap_remove(idx);
removed = true;
} else {
idx += 1;
}
}
removed
}
while self.ctx.parts().handles.len() > 2 {
let handle = self.ctx.parts().handles.pop().unwrap();
// remove item from ContextFut.items in case associated item is already merged
if !remove_item_by_handle(&mut self.items, &handle) {
// item is not merged into ContextFut.items yet,
// so it should be in ContextParts.items
remove_item_by_handle(&mut self.ctx.parts().items, &handle);
}
}
}
}
#[doc(hidden)]
impl<A, C> Future for ContextFut<A, C>
where
C: AsyncContextParts<A> + Unpin,
A: Actor<Context = C>,
{
type Output = ();
fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
let this = self.get_mut();
if !this.ctx.parts().flags.contains(ContextFlags::STARTED) {
this.ctx.parts().flags.insert(ContextFlags::STARTED);
Actor::started(&mut this.act, &mut this.ctx);
// check cancelled handles, just in case
if this.merge() {
this.clean_canceled_handle();
}
}
'outer: loop {
// check wait futures. order does matter
// ctx.wait() always add to the back of the list
// and we always have to check most recent future
while !this.wait.is_empty() && !this.stopping() {
let idx = this.wait.len() - 1;
let item = this.wait.last_mut().unwrap();
ready!(Pin::new(item).poll(&mut this.act, &mut this.ctx, cx));
this.wait.remove(idx);
this.merge();
}
// process mailbox
this.mailbox.poll(&mut this.act, &mut this.ctx, cx);
if !this.wait.is_empty() && !this.stopping() {
continue;
}
// process items
let mut idx = 0;
while idx < this.items.len() && !this.stopping() {
this.ctx.parts().handles[1] = this.items[idx].0;
match Pin::new(&mut this.items[idx].1).poll(&mut this.act, &mut this.ctx, cx) {
Poll::Pending => {
// got new waiting item. merge
if this.ctx.waiting() {
this.merge();
}
// check cancelled handles
if this.ctx.parts().handles.len() > 2 {
// this code is not very efficient, relaying on fact that
// cancellation should be rear also number of futures
// in actor context should be small
this.clean_canceled_handle();
continue 'outer;
}
// item scheduled wait future
if !this.wait.is_empty() && !this.stopping() {
// move current item to end of poll queue
// otherwise it is possible that same item generate wait
// future and prevents polling
// of other items
let next = this.items.len() - 1;
if idx != next {
this.items.swap(idx, next);
}
continue 'outer;
} else {
idx += 1;
}
}
Poll::Ready(()) => {
this.items.swap_remove(idx);
// got new waiting item. merge
if this.ctx.waiting() {
this.merge();
}
// one of the items scheduled wait future
if !this.wait.is_empty() && !this.stopping() {
continue 'outer;
}
}
}
}
this.ctx.parts().handles[1] = SpawnHandle::default();
// merge returns true if context contains new items or handles to be cancelled
if this.merge() && !this.ctx.parts().flags.contains(ContextFlags::STOPPING) {
// if we have no item to process, cancelled handles wouldn't be
// reaped in the above loop. this means this.merge() will never
// be false and the poll() never ends. so, discard the handles
// as we're sure there are no more items to be cancelled.
if this.items.is_empty() {
this.ctx.parts().handles.truncate(2);
}
continue;
}
// check state
if this.ctx.parts().flags.contains(ContextFlags::RUNNING) {
// possible stop condition
if !this.alive() && Actor::stopping(&mut this.act, &mut this.ctx) == Running::Stop {
this.ctx.parts().flags = ContextFlags::STOPPED | ContextFlags::STARTED;
Actor::stopped(&mut this.act, &mut this.ctx);
return Poll::Ready(());
}
} else if this.ctx.parts().flags.contains(ContextFlags::STOPPING) {
if Actor::stopping(&mut this.act, &mut this.ctx) == Running::Stop {
this.ctx.parts().flags = ContextFlags::STOPPED | ContextFlags::STARTED;
Actor::stopped(&mut this.act, &mut this.ctx);
return Poll::Ready(());
} else {
this.ctx.parts().flags.remove(ContextFlags::STOPPING);
this.ctx.parts().flags.insert(ContextFlags::RUNNING);
continue;
}
} else if this.ctx.parts().flags.contains(ContextFlags::STOPPED) {
Actor::stopped(&mut this.act, &mut this.ctx);
return Poll::Ready(());
}
return Poll::Pending;
}
}
}
================================================
FILE: actix/src/context_items.rs
================================================
use std::{
future::Future,
pin::Pin,
task::{self, Poll},
time::Duration,
};
use futures_core::{ready, stream::Stream};
use pin_project_lite::pin_project;
use crate::{
actor::{Actor, ActorContext, AsyncContext},
clock::Sleep,
fut::ActorFuture,
handler::{Handler, Message, MessageResponse},
};
pub(crate) struct ActorWaitItem<A: Actor>(Pin<Box<dyn ActorFuture<A, Output = ()>>>);
impl<A> ActorWaitItem<A>
where
A: Actor,
A::Context: ActorContext + AsyncContext<A>,
{
#[inline]
pub fn new<F>(fut: F) -> Self
where
F: ActorFuture<A, Output = ()> + 'static,
{
ActorWaitItem(Box::pin(fut))
}
pub fn poll(
mut self: Pin<&mut Self>,
act: &mut A,
ctx: &mut A::Context,
task: &mut task::Context<'_>,
) -> Poll<()> {
match self.0.as_mut().poll(act, ctx, task) {
Poll::Pending => {
if ctx.state().alive() {
Poll::Pending
} else {
Poll::Ready(())
}
}
Poll::Ready(_) => Poll::Ready(()),
}
}
}
pin_project! {
pub(crate) struct ActorDelayedMessageItem<M: Message>{
msg: Option<M>,
#[pin]
timeout: Sleep,
}
}
impl<M: Message> ActorDelayedMessageItem<M> {
pub fn new(msg: M, timeout: Duration) -> Self {
Self {
msg: Some(msg),
timeout: actix_rt::time::sleep(timeout),
}
}
}
impl<A, M> ActorFuture<A> for ActorDelayedMessageItem<M>
where
A: Actor + Handler<M>,
A::Context: AsyncContext<A>,
M: Message + 'static,
{
type Output = ();
fn poll(
self: Pin<&mut Self>,
act: &mut A,
ctx: &mut A::Context,
task: &mut task::Context<'_>,
) -> Poll<Self::Output> {
let this = self.project();
ready!(this.timeout.poll(task));
let fut = A::handle(act, this.msg.take().unwrap(), ctx);
fut.handle(ctx, None);
Poll::Ready(())
}
}
pub(crate) struct ActorMessageItem<M: Message> {
msg: Option<M>,
}
impl<M: Message> Unpin for ActorMessageItem<M> {}
impl<M: Message> ActorMessageItem<M> {
pub fn new(msg: M) -> Self {
Self { msg: Some(msg) }
}
}
impl<A, M> ActorFuture<A> for ActorMessageItem<M>
where
A: Actor + Handler<M>,
A::Context: AsyncContext<A>,
M: Message + 'static,
{
type Output = ();
fn poll(
self: Pin<&mut Self>,
act: &mut A,
ctx: &mut A::Context,
_: &mut task::Context<'_>,
) -> Poll<Self::Output> {
let this = self.get_mut();
let fut = Handler::handle(act, this.msg.take().unwrap(), ctx);
fut.handle(ctx, None);
Poll::Ready(())
}
}
pin_project! {
pub(crate) struct ActorMessageStreamItem<S>{
#[pin]
stream: S,
}
}
impl<S> ActorMessageStreamItem<S> {
pub fn new(st: S) -> Self {
Self { stream: st }
}
}
impl<A, S> ActorFuture<A> for ActorMessageStreamItem<S>
where
S: Stream,
A: Actor + Handler<S::Item>,
A::Context: AsyncContext<A>,
S::Item: Message + 'static,
{
type Output = ();
fn poll(
self: Pin<&mut Self>,
act: &mut A,
ctx: &mut A::Context,
task: &mut task::Context<'_>,
) -> Poll<Self::Output> {
let mut this = self.project();
while let Some(msg) = ready!(this.stream.as_mut().poll_next(task)) {
let fut = Handler::handle(act, msg, ctx);
fut.handle(ctx, None);
if ctx.waiting() {
return Poll::Pending;
}
}
Poll::Ready(())
}
}
================================================
FILE: actix/src/fut/future/either.rs
================================================
use std::{
pin::Pin,
task::{Context, Poll},
};
use futures_util::future::Either;
use crate::{actor::Actor, fut::ActorFuture};
impl<A, B, Act> ActorFuture<Act> for Either<A, B>
where
A: ActorFuture<Act>,
B: ActorFuture<Act, Output = A::Output>,
Act: Actor,
{
type Output = A::Output;
fn poll(
self: Pin<&mut Self>,
act: &mut Act,
ctx: &mut Act::Context,
task: &mut Context<'_>,
) -> Poll<A::Output> {
// SAFETY:
//
// Copied from futures_util::future::Either::project method.
// This is used to expose this method to public.
// It has the same safety as the private one.
let this = unsafe {
match self.get_unchecked_mut() {
Either::Left(a) => Either::Left(Pin::new_unchecked(a)),
Either::Right(b) => Either::Right(Pin::new_unchecked(b)),
}
};
match this {
Either::Left(left) => left.poll(act, ctx, task),
Either::Right(right) => right.poll(act, ctx, task),
}
}
}
================================================
FILE: actix/src/fut/future/map.rs
================================================
use std::{
pin::Pin,
task::{Context, Poll},
};
use futures_core::ready;
use pin_project_lite::pin_project;
use crate::{actor::Actor, fut::ActorFuture};
pin_project! {
/// Future for the [`map`](super::ActorFutureExt::map) method.
#[project = MapProj]
#[project_replace = MapProjReplace]
#[derive(Debug)]
#[must_use = "futures do nothing unless you `.await` or poll them"]
pub enum Map<Fut, F> {
Incomplete {
#[pin]
future: Fut,
f: F,
},
Complete,
}
}
impl<Fut, F> Map<Fut, F> {
pub(super) fn new(future: Fut, f: F) -> Self {
Self::Incomplete { future, f }
}
}
impl<U, Fut, A, F> ActorFuture<A> for Map<Fut, F>
where
Fut: ActorFuture<A>,
A: Actor,
F: FnOnce(Fut::Output, &mut A, &mut A::Context) -> U,
{
type Output = U;
fn poll(
mut self: Pin<&mut Self>,
act: &mut A,
ctx: &mut A::Context,
task: &mut Context<'_>,
) -> Poll<Self::Output> {
match self.as_mut().project() {
MapProj::Incomplete { future, .. } => {
let output = ready!(future.poll(act, ctx, task));
match self.project_replace(Map::Complete) {
MapProjReplace::Incomplete { f, .. } => Poll::Ready(f(output, act, ctx)),
MapProjReplace::Complete => unreachable!(),
}
}
MapProj::Complete => {
panic!("Map must not be polled after it returned `Poll::Ready`")
}
}
}
}
================================================
FILE: actix/src/fut/future/mod.rs
================================================
use std::{
future::Future,
marker::PhantomData,
ops::{Deref, DerefMut},
pin::Pin,
task::{Context, Poll},
time::Duration,
};
pub use map::Map;
use pin_project_lite::pin_project;
pub use then::Then;
pub use timeout::Timeout;
use crate::actor::Actor;
mod either;
mod map;
pub mod result;
mod then;
mod timeout;
/// Trait for types which are a placeholder of a value that may become
/// available at some later point in time.
///
/// [`ActorFuture`] is very similar to a regular [`Future`], only with subsequent combinator
/// closures accepting the actor and its context, in addition to the result.
///
/// [`ActorFuture`] allows for use cases where future processing requires access to the actor or
/// its context.
///
/// Here is an example of a handler on a single actor, deferring work to another actor, and then
/// updating the initiating actor's state:
///
/// ```no_run
/// use actix::prelude::*;
///
/// // The response type returned by the actor future
/// type OriginalActorResponse = ();
/// // The error type returned by the actor future
/// type MessageError = ();
/// // This is the needed result for the DeferredWork message
/// // It's a result that combine both Response and Error from the future response.
/// type DeferredWorkResult = Result<OriginalActorResponse, MessageError>;
/// #
/// # struct ActorState {}
/// #
/// # impl ActorState {
/// # fn update_from(&mut self, _result: ()) {}
/// # }
/// #
/// # struct OtherActor {}
/// #
/// # impl Actor for OtherActor {
/// # type Context = Context<Self>;
/// # }
/// #
/// # impl Handler<OtherMessage> for OtherActor {
/// # type Result = ();
/// #
/// # fn handle(&mut self, _msg: OtherMessage, _ctx: &mut Context<Self>) -> Self::Result {}
/// # }
/// #
/// # struct OriginalActor{
/// # other_actor: Addr<OtherActor>,
/// # inner_state: ActorState
/// # }
/// #
/// # impl Actor for OriginalActor{
/// # type Context = Context<Self>;
/// # }
/// #
/// # #[derive(Message)]
/// # #[rtype(result = "Result<(), MessageError>")]
/// # struct DeferredWork {}
/// #
/// # #[derive(Message)]
/// # #[rtype(result = "()")]
/// # struct OtherMessage {}
///
/// impl Handler<DeferredWork> for OriginalActor {
/// // Notice the `Response` is an `ActorFuture`-ized version of `Self::Message::Result`.
/// type Result = ResponseActFuture<Self, DeferredWorkResult>;
///
/// fn handle(&mut self, _msg: DeferredWork, _ctx: &mut Context<Self>) -> Self::Result {
/// // this creates a `Future` representing the `.send` and subsequent
/// // `Result` from `other_actor`
/// let update_self = self.other_actor
/// .send(OtherMessage {})
/// // Wrap that future so chained handlers can access the actor
/// // (`self` in the synchronous code) as well as the context.
/// .into_actor(self)
/// // once the wrapped future resolves, update this actor's state
/// .map(|result, actor, _ctx| {
/// match result {
/// Ok(v) => {
/// // update actor (self) state
/// actor.inner_state.update_from(v);
/// Ok(())
/// },
/// // Failed to send message to other_actor
/// Err(_e) => Err(()),
/// }
/// });
///
/// // box and return the wrapped future
/// Box::pin(update_self)
/// }
/// }
/// ```
///
/// See also [`WrapFuture::into_actor()`] which provides future conversion.
pub trait ActorFuture<A: Actor> {
/// The type of value produced on completion.
type Output;
fn poll(
self: Pin<&mut Self>,
srv: &mut A,
ctx: &mut A::Context,
task: &mut Context<'_>,
) -> Poll<Self::Output>;
}
pub trait ActorFutureExt<A: Actor>: ActorFuture<A> {
/// Map this future's result to a different type, returning a new future of
/// the resulting type.
fn map<F, U>(self, f: F) -> Map<Self, F>
where
F: FnOnce(Self::Output, &mut A, &mut A::Context) -> U,
Self: Sized,
{
Map::new(self, f)
}
/// Chain on a computation for when a future finished, passing the result of
/// the future to the provided closure `f`.
fn then<F, Fut>(self, f: F) -> Then<Self, Fut, F>
where
F: FnOnce(Self::Output, &mut A, &mut A::Context) -> Fut,
Fut: ActorFuture<A>,
Self: Sized,
{
then::new(self, f)
}
/// Add timeout to futures chain.
///
/// `Err(())` returned as a timeout error.
fn timeout(self, timeout: Duration) -> Timeout<Self>
where
Self: Sized,
{
Timeout::new(self, timeout)
}
/// Wrap the future in a Box, pinning it.
///
/// A shortcut for wrapping in [`Box::pin`].
fn boxed_local(self) -> LocalBoxActorFuture<A, Self::Output>
where
Self: Sized + 'static,
{
Box::pin(self)
}
}
impl<F, A> ActorFutureExt<A> for F
where
F: ActorFuture<A>,
A: Actor,
{
}
/// Type alias for a pinned box [`ActorFuture`] trait object.
pub type LocalBoxActorFuture<A, I> = Pin<Box<dyn ActorFuture<A, Output = I>>>;
impl<F, A> ActorFuture<A> for Box<F>
where
F: ActorFuture<A> + Unpin + ?Sized,
A: Actor,
{
type Output = F::Output;
fn poll(
mut self: Pin<&mut Self>,
srv: &mut A,
ctx: &mut A::Context,
task: &mut Context<'_>,
) -> Poll<Self::Output> {
Pin::new(&mut **self.as_mut()).poll(srv, ctx, task)
}
}
impl<P, A> ActorFuture<A> for Pin<P>
where
P: Unpin + DerefMut,
<P as Deref>::Target: ActorFuture<A>,
A: Actor,
{
type Output = <<P as Deref>::Target as ActorFuture<A>>::Output;
fn poll(
self: Pin<&mut Self>,
srv: &mut A,
ctx: &mut A::Context,
task: &mut Context<'_>,
) -> Poll<Self::Output> {
Pin::get_mut(self).as_mut().poll(srv, ctx, task)
}
}
/// Helper trait that allows conversion of normal future into [`ActorFuture`]
pub trait WrapFuture<A>
where
A: Actor,
{
/// The future that this type can be converted into.
type Future: ActorFuture<A>;
#[deprecated(since = "0.11.0", note = "Please use WrapFuture::into_actor")]
#[doc(hidden)]
fn actfuture(self) -> Self::Future;
/// Convert normal future to a [`ActorFuture`]
fn into_actor(self, a: &A) -> Self::Future;
}
impl<F: Future, A: Actor> WrapFuture<A> for F {
type Future = FutureWrap<F, A>;
#[doc(hidden)]
fn actfuture(self) -> Self::Future {
wrap_future(self)
}
fn into_actor(self, _: &A) -> Self::Future {
wrap_future(self)
}
}
pin_project! {
pub struct FutureWrap<F, A>
where
F: Future,
A: Actor,
{
#[pin]
fut: F,
_act: PhantomData<A>
}
}
/// Converts normal future into [`ActorFuture`], allowing its processing to
/// use the actor's state.
///
/// See the documentation for [`ActorFuture`] for a practical example involving both
/// [`wrap_future`] and [`ActorFuture`]
pub fn wrap_future<F, A>(f: F) -> FutureWrap<F, A>
where
F: Future,
A: Actor,
{
FutureWrap {
fut: f,
_act: PhantomData,
}
}
impl<F, A> ActorFuture<A> for FutureWrap<F, A>
where
F: Future,
A: Actor,
{
type Output = F::Output;
fn poll(
self: Pin<&mut Self>,
_: &mut A,
_: &mut A::Context,
task: &mut Context<'_>,
) -> Poll<Self::Output> {
self.project().fut.poll(task)
}
}
================================================
FILE: actix/src/fut/future/result.rs
================================================
//! Definition of the [`Ready`] (immediately finished) combinator
use std::{
future::Future,
pin::Pin,
task::{self, Poll},
};
// TODO: remove re-export and encourage direct usage of std and/or futures crate types.
pub use futures_util::future::{ready, Ready};
use crate::{actor::Actor, fut::ActorFuture};
/// Creates a new "leaf future" which will resolve with the given result.
///
/// The returned future represents a computation which is finished immediately.
/// This can be useful with the `finished` and `failed` base future types to
/// convert an immediate value to a future to interoperate elsewhere.
///
/// # Examples
///
/// ```
/// use actix::{fut, Actor, Context};
///
/// struct MyActor;
/// impl Actor for MyActor {
/// type Context = Context<Self>;
/// }
///
/// let future_of_1 = fut::result::<u32, u32>(Ok(1));
/// let future_of_err_2 = fut::result::<u32, u32>(Err(2));
/// ```
pub fn result<T, E>(r: Result<T, E>) -> Ready<Result<T, E>> {
ready(r)
}
/// Creates a "leaf future" from an immediate value of a finished and
/// successful computation.
///
/// The returned future is similar to `result` where it will immediately run a
/// scheduled callback with the provided value.
///
/// # Examples
///
/// ```
/// use actix::fut::*;
/// use actix::{Actor, Context};
///
/// struct MyActor;
/// impl Actor for MyActor {
/// type Context = Context<Self>;
/// }
///
/// let future_of_1 = ok::<u32, u32>(1);
/// ```
pub fn ok<T, E>(t: T) -> Ready<Result<T, E>> {
ready(Ok(t))
}
/// Creates a "leaf future" from an immediate value of a failed computation.
///
/// The returned future is similar to `result` where it will immediately run a
/// scheduled callback with the provided value.
///
/// # Examples
///
/// ```
/// use actix::{fut, Actor, Context};
///
/// struct MyActor;
/// impl Actor for MyActor {
/// type Context = Context<Self>;
/// }
///
/// let future_of_err_1 = fut::err::<u32, u32>(1);
/// ```
pub fn err<T, E>(e: E) -> Ready<Result<T, E>> {
ready(Err(e))
}
impl<T, A> ActorFuture<A> for Ready<T>
where
A: Actor,
{
type Output = T;
#[inline]
fn poll(
self: Pin<&mut Self>,
_: &mut A,
_: &mut A::Context,
cx: &mut task::Context<'_>,
) -> Poll<Self::Output> {
Future::poll(self, cx)
}
}
================================================
FILE: actix/src/fut/future/then.rs
================================================
use std::{
pin::Pin,
task::{self, Poll},
};
use futures_core::ready;
use pin_project_lite::pin_project;
use crate::{actor::Actor, fut::ActorFuture};
pin_project! {
/// Future for the [`then`](super::ActorFutureExt::then) combinator, chaining computations on the end of
/// another future regardless of its outcome.
///
/// This is created by the `ActorFuture::then` method.
#[project = ThenProj]
#[derive(Debug)]
#[must_use = "futures do nothing unless polled"]
pub enum Then<A, B, F> {
First {
#[pin]
fut1: A,
data: Option<F>,
},
Second {
#[pin]
fut2: B
},
Empty,
}
}
pub(super) fn new<A, B, F, Act>(future: A, f: F) -> Then<A, B, F>
where
A: ActorFuture<Act>,
B: ActorFuture<Act>,
Act: Actor,
{
Then::First {
fut1: future,
data: Some(f),
}
}
impl<A, B, F, Act> ActorFuture<Act> for Then<A, B, F>
where
A: ActorFuture<Act>,
B: ActorFuture<Act>,
F: FnOnce(A::Output, &mut Act, &mut Act::Context) -> B,
Act: Actor,
{
type Output = B::Output;
fn poll(
mut self: Pin<&mut Self>,
act: &mut Act,
ctx: &mut Act::Context,
task: &mut task::Context<'_>,
) -> Poll<B::Output> {
match self.as_mut().project() {
ThenProj::First { fut1, data } => {
let output = ready!(fut1.poll(act, ctx, task));
let data = data.take().unwrap();
let fut2 = data(output, act, ctx);
self.set(Then::Second { fut2 });
self.poll(act, ctx, task)
}
ThenProj::Second { fut2 } => {
let res = ready!(fut2.poll(act, ctx, task));
self.set(Then::Empty);
Poll::Ready(res)
}
ThenProj::Empty => panic!("ActorFuture polled after finish"),
}
}
}
================================================
FILE: actix/src/fut/future/timeout.rs
================================================
use std::{
future::Future,
pin::Pin,
task::{Context, Poll},
time::Duration,
};
use pin_project_lite::pin_project;
use crate::{
actor::Actor,
clock::{sleep, Sleep},
fut::ActorFuture,
};
pin_project! {
/// Future for the [`timeout`](super::ActorFutureExt::timeout) combinator, interrupts computations if it takes
/// more than [`timeout`](super::ActorFutureExt::timeout).
///
/// This is created by the [`timeout`](super::ActorFutureExt::timeout) method.
#[derive(Debug)]
#[must_use = "futures do nothing unless polled"]
pub struct Timeout<F>{
#[pin]
fut: F,
#[pin]
timeout: Sleep,
}
}
impl<F> Timeout<F> {
pub(super) fn new(future: F, timeout: Duration) -> Self {
Self {
fut: future,
timeout: sleep(timeout),
}
}
}
impl<F, A> ActorFuture<A> for Timeout<F>
where
F: ActorFuture<A>,
A: Actor,
{
type Output = Result<F::Output, ()>;
fn poll(
self: Pin<&mut Self>,
act: &mut A,
ctx: &mut A::Context,
task: &mut Context<'_>,
) -> Poll<Self::Output> {
let this = self.project();
match this.fut.poll(act, ctx, task) {
Poll::Ready(res) => Poll::Ready(Ok(res)),
Poll::Pending => this.timeout.poll(task).map(Err),
}
}
}
================================================
FILE: actix/src/fut/mod.rs
================================================
//! Custom `Future` and `Stream` implementation with `actix` support.
pub mod future;
pub mod stream;
pub mod try_future;
pub use self::{
future::{
result::{err, ok, ready, result, Ready},
wrap_future, ActorFuture, ActorFutureExt, LocalBoxActorFuture, WrapFuture,
},
stream::{wrap_stream, ActorStream, ActorStreamExt, WrapStream},
try_future::{ActorTryFuture, ActorTryFutureExt},
};
================================================
FILE: actix/src/fut/stream/collect.rs
================================================
use std::{
mem,
pin::Pin,
task::{Context, Poll},
};
use futures_core::ready;
use pin_project_lite::pin_project;
use super::ActorStream;
use crate::{actor::Actor, fut::future::ActorFuture};
pin_project! {
/// Future for the [`collect`](super::ActorStreamExt::collect) method.
#[derive(Debug)]
#[must_use = "futures do nothing unless you `.await` or poll them"]
pub struct Collect<S, C> {
#[pin]
stream: S,
collection: C,
}
}
impl<S, C> Collect<S, C>
where
C: Default,
{
pub(super) fn new(stream: S) -> Self {
Self {
stream,
collection: Default::default(),
}
}
}
impl<S, A, C> ActorFuture<A> for Collect<S, C>
where
S: ActorStream<A>,
A: Actor,
C: Default + Extend<S::Item>,
{
type Output = C;
fn poll(
mut self: Pin<&mut Self>,
act: &mut A,
ctx: &mut A::Context,
task: &mut Context<'_>,
) -> Poll<Self::Output> {
let mut this = self.as_mut().project();
loop {
match ready!(this.stream.as_mut().poll_next(act, ctx, task)) {
Some(e) => this.collection.extend(Some(e)),
None => return Poll::Ready(mem::take(this.collection)),
}
}
}
}
================================================
FILE: actix/src/fut/stream/finish.rs
================================================
use std::{
pin::Pin,
task::{Context, Poll},
};
use futures_core::ready;
use pin_project_lite::pin_project;
use crate::{
actor::Actor,
fut::{ActorFuture, ActorStream},
};
pin_project! {
/// Future for the [`finish`](super::ActorStreamExt::finish) method.
#[derive(Debug)]
#[must_use = "streams do nothing unless polled"]
pub struct Finish<S> {
#[pin]
pub(crate) stream: S
}
}
impl<S> Finish<S> {
pub fn new(stream: S) -> Finish<S> {
Finish { stream }
}
}
impl<S, A> ActorFuture<A> for Finish<S>
where
S: ActorStream<A>,
A: Actor,
{
type Output = ();
fn poll(
mut self: Pin<&mut Self>,
act: &mut A,
ctx: &mut A::Context,
task: &mut Context<'_>,
) -> Poll<()> {
let mut this = self.as_mut().project();
while ready!(this.stream.as_mut().poll_next(act, ctx, task)).is_some() {}
Poll::Ready(())
}
}
================================================
FILE: actix/src/fut/stream/fold.rs
================================================
use std::{
pin::Pin,
task::{Context, Poll},
};
use futures_core::ready;
use pin_project_lite::pin_project;
use crate::{
actor::Actor,
fut::{ActorFuture, ActorStream},
};
pin_project! {
/// Stream for the [`fold`](super::ActorStreamExt::fold) method.
#[derive(Debug)]
#[must_use = "streams do nothing unless polled"]
pub struct Fold<S, F, Fut, T> {
#[pin]
stream: S,
f: F,
accum: Option<T>,
#[pin]
future: Option<Fut>,
}
}
pub(super) fn new<S, A, F, Fut>(stream: S, f: F, t: Fut::Output) -> Fold<S, F, Fut, Fut::Output>
where
S: ActorStream<A>,
A: Actor,
F: FnMut(Fut::Output, S::Item, &mut A, &mut A::Context) -> Fut,
Fut: ActorFuture<A>,
{
Fold {
stream,
f,
accum: Some(t),
future: None,
}
}
impl<S, A, F, Fut> ActorFuture<A> for Fold<S, F, Fut, Fut::Output>
where
S: ActorStream<A>,
A: Actor,
F: FnMut(Fut::Output, S::Item, &mut A, &mut A::Context) -> Fut,
Fut: ActorFuture<A>,
{
type Output = Fut::Output;
fn poll(
self: Pin<&mut Self>,
act: &mut A,
ctx: &mut A::Context,
task: &mut Context<'_>,
) -> Poll<Self::Output> {
let mut this = self.project();
Poll::Ready(loop {
if let Some(fut) = this.future.as_mut().as_pin_mut() {
// we're currently processing a future to produce a new accum value
*this.accum = Some(ready!(fut.poll(act, ctx, task)));
this.future.set(None);
} else if this.accum.is_some() {
// we're waiting on a new item from the stream
let res = ready!(this.stream.as_mut().poll_next(act, ctx, task));
let a = this.accum.take().unwrap();
if let Some(item) = res {
this.future.set(Some((this.f)(a, item, act, ctx)));
} else {
break a;
}
} else {
panic!("Fold polled after completion")
}
})
}
}
================================================
FILE: actix/src/fut/stream/map.rs
================================================
use std::{
pin::Pin,
task::{Context, Poll},
};
use futures_core::ready;
use pin_project_lite::pin_project;
use crate::{actor::Actor, fut::ActorStream};
pin_project! {
/// Stream for the [`map`](super::ActorStreamExt::map) method.
#[derive(Debug)]
#[must_use = "streams do nothing unless polled"]
pub struct Map<S, F> {
#[pin]
stream: S,
f: F,
}
}
pub(super) fn new<S, A, F, U>(stream: S, f: F) -> Map<S, F>
where
S: ActorStream<A>,
A: Actor,
F: FnMut(S::Item, &mut A, &mut A::Context) -> U,
{
Map { stream, f }
}
impl<S, A, F, U> ActorStream<A> for Map<S, F>
where
S: ActorStream<A>,
A: Actor,
F: FnMut(S::Item, &mut A, &mut A::Context) -> U,
{
type Item = U;
fn poll_next(
self: Pin<&mut Self>,
act: &mut A,
ctx: &mut A::Context,
task: &mut Context<'_>,
) -> Poll<Option<Self::Item>> {
let mut this = self.project();
let res = ready!(this.stream.as_mut().poll_next(act, ctx, task));
Poll::Ready(res.map(|x| (this.f)(x, act, ctx)))
}
}
================================================
FILE: actix/src/fut/stream/mod.rs
================================================
use std::{
marker::PhantomData,
pin::Pin,
task::{Context, Poll},
time::Duration,
};
pub use collect::Collect;
pub use finish::Finish;
pub use fold::Fold;
use futures_core::stream::Stream;
pub use map::Map;
use pin_project_lite::pin_project;
pub use skip_while::SkipWhile;
pub use take_while::TakeWhile;
pub use then::Then;
pub use timeout::Timeout;
use super::future::ActorFuture;
use crate::actor::Actor;
mod collect;
mod finish;
mod fold;
mod map;
mod skip_while;
mod take_while;
mod then;
mod timeout;
/// A stream of values, not all of which may have been produced yet.
///
/// This is similar to `futures_util::stream::Stream` trait, except it works with `Actor`
pub trait ActorStream<A: Actor> {
/// The type of item this stream will yield on success.
type Item;
fn poll_next(
self: Pin<&mut Self>,
srv: &mut A,
ctx: &mut A::Context,
task: &mut Context<'_>,
) -> Poll<Option<Self::Item>>;
}
pub trait ActorStreamExt<A: Actor>: ActorStream<A> {
/// Maps this stream's items to a different type, returning a new stream of
/// the resulting type.
///
/// The provided closure is executed over all elements of this stream as
/// they are made available. It is executed inline with calls to
/// [`poll_next`](ActorStream::poll_next).
///
/// Note that this function consumes the stream passed into it and returns a
/// wrapped version of it, similar to the existing `map` methods in the
/// standard library.
fn map<F, U>(self, f: F) -> Map<Self, F>
where
F: FnMut(Self::Item, &mut A, &mut A::Context) -> U,
Self: Sized,
{
map::new(self, f)
}
/// Computes from this stream's items new items of a different type using
/// an asynchronous closure.
///
/// The provided closure `f` will be called with an `Item` once a value is
/// ready, it returns a future which will then be run to completion
/// to produce the next value on this stream.
///
/// Note that this function consumes the stream passed into it and returns a
/// wrapped version of it.
fn then<F, Fut>(self, f: F) -> Then<Self, F, Fut>
where
F: FnMut(Self::Item, &mut A, &mut A::Context) -> Fut,
Fut: ActorFuture<A>,
Self: Sized,
{
then::new(self, f)
}
/// Execute an accumulating asynchronous computation over a stream,
/// collecting all the values into one final result.
///
/// This combinator will accumulate all values returned by this stream
/// according to the closure provided. The initial state is also provided to
/// this method and then is returned again by each execution of the closure.
/// Once the entire stream has been exhausted the returned future will
/// resolve to this value.
fn fold<F, Fut>(self, init: Fut::Output, f: F) -> Fold<Self, F, Fut, Fut::Output>
where
F: FnMut(Fut::Output, Self::Item, &mut A, &mut A::Context) -> Fut,
Fut: ActorFuture<A>,
Self: Sized,
{
fold::new(self, f, init)
}
/// Take elements from this stream while the provided asynchronous predicate
/// resolves to `true`.
///
/// This function, like `Iterator::take_while`, will take elements from the
/// stream until the predicate `f` resolves to `false`. Once one element
/// returns `false`, it will always return that the stream is done.
fn take_while<F, Fut>(self, f: F) -> TakeWhile<Self, Self::Item, F, Fut>
where
F: FnMut(&Self::Item, &mut A, &mut A::Context) -> Fut,
Fut: ActorFuture<A, Output = bool>,
Self: Sized,
{
take_while::new(self, f)
}
/// Skip elements on this stream while the provided asynchronous predicate
/// resolves to `true`.
///
/// This function, like `Iterator::skip_while`, will skip elements on the
/// stream until the predicate `f` resolves to `false`. Once one element
/// returns `false`, all future elements will be returned from the underlying
/// stream.
fn skip_while<F, Fut>(self, f: F) -> SkipWhile<Self, Self::Item, F, Fut>
where
F: FnMut(&Self::Item, &mut A, &mut A::Context) -> Fut,
Fut: ActorFuture<A, Output = bool>,
Self: Sized,
{
skip_while::new(self, f)
}
/// Add timeout to stream.
///
/// `Err(())` returned as a timeout error.
fn timeout(self, timeout: Duration) -> Timeout<Self>
where
Self: Sized,
{
Timeout::new(self, timeout)
}
/// Transforms a stream into a collection, returning a
/// future representing the result of that computation.
///
/// The returned future will be resolved when the stream terminates.
fn collect<C>(self) -> Collect<Self, C>
where
C: Default + Extend<Self::Item>,
Self: Sized,
{
Collect::new(self)
}
/// Transforms a stream t
gitextract_y92ftxtg/ ├── .codecov.yml ├── .github/ │ ├── ISSUE_TEMPLATE/ │ │ ├── bug_report.md │ │ └── config.yml │ ├── PULL_REQUEST_TEMPLATE.md │ ├── dependabot.yml │ └── workflows/ │ ├── ci-post-merge.yml │ ├── ci.yml │ ├── clippy-fmt.yml │ └── coverage.yml ├── .gitignore ├── .prettierrc.yml ├── .rustfmt.toml ├── .vscode/ │ └── settings.json ├── CODE_OF_CONDUCT.md ├── Cargo.toml ├── LICENSE-APACHE ├── LICENSE-MIT ├── actix/ │ ├── CHANGES.md │ ├── Cargo.toml │ ├── MIGRATION.md │ ├── README.md │ ├── examples/ │ │ ├── README.md │ │ ├── fibonacci.rs │ │ ├── mock.rs │ │ ├── ping.rs │ │ ├── ring.rs │ │ ├── weak_addr.rs │ │ └── weak_recipient.rs │ ├── src/ │ │ ├── actor.rs │ │ ├── actors/ │ │ │ ├── mocker.rs │ │ │ └── mod.rs │ │ ├── address/ │ │ │ ├── channel.rs │ │ │ ├── envelope.rs │ │ │ ├── message.rs │ │ │ ├── mod.rs │ │ │ └── queue.rs │ │ ├── clock.rs │ │ ├── context.rs │ │ ├── context_impl.rs │ │ ├── context_items.rs │ │ ├── fut/ │ │ │ ├── future/ │ │ │ │ ├── either.rs │ │ │ │ ├── map.rs │ │ │ │ ├── mod.rs │ │ │ │ ├── result.rs │ │ │ │ ├── then.rs │ │ │ │ └── timeout.rs │ │ │ ├── mod.rs │ │ │ ├── stream/ │ │ │ │ ├── collect.rs │ │ │ │ ├── finish.rs │ │ │ │ ├── fold.rs │ │ │ │ ├── map.rs │ │ │ │ ├── mod.rs │ │ │ │ ├── skip_while.rs │ │ │ │ ├── take_while.rs │ │ │ │ ├── then.rs │ │ │ │ └── timeout.rs │ │ │ └── try_future/ │ │ │ ├── and_then.rs │ │ │ ├── map_err.rs │ │ │ ├── map_ok.rs │ │ │ └── mod.rs │ │ ├── handler.rs │ │ ├── io.rs │ │ ├── lib.rs │ │ ├── mailbox.rs │ │ ├── registry.rs │ │ ├── stream.rs │ │ ├── supervisor.rs │ │ ├── sync.rs │ │ └── utils.rs │ └── tests/ │ ├── derive.rs │ ├── test_actor.rs │ ├── test_address.rs │ ├── test_arbiter.rs │ ├── test_atomic_response.rs │ ├── test_connected.rs │ ├── test_context.rs │ ├── test_fut.rs │ ├── test_lifecycle.rs │ ├── test_messages.rs │ ├── test_sink.rs │ ├── test_supervisor.rs │ └── test_sync.rs ├── actix-broker/ │ ├── CHANGES.md │ ├── Cargo.toml │ ├── LICENSE-APACHE │ ├── LICENSE-MIT │ ├── README.md │ ├── benches/ │ │ └── broker.rs │ ├── examples/ │ │ ├── actix-web.rs │ │ └── basic.rs │ ├── src/ │ │ ├── broker.rs │ │ ├── issue.rs │ │ ├── lib.rs │ │ ├── msgs.rs │ │ └── subscribe.rs │ └── tests/ │ ├── delivery.rs │ └── general.rs ├── actix-derive/ │ ├── CHANGES.md │ ├── Cargo.toml │ ├── README.md │ ├── src/ │ │ ├── lib.rs │ │ ├── message.rs │ │ └── message_response.rs │ └── tests/ │ ├── test_macro.rs │ ├── trybuild/ │ │ ├── message-response.rs │ │ ├── message.rs │ │ └── rt-main.rs │ └── trybuild.rs └── justfile
SYMBOL INDEX (1073 symbols across 74 files)
FILE: actix-broker/benches/broker.rs
type MessageTest (line 21) | struct MessageTest {
type ActorTest (line 27) | struct ActorTest;
type Result (line 38) | type Result = ();
method handle (line 39) | fn handle(&mut self, msg: MessageTest, _ctx: &mut Self::Context) -> Se...
type Context (line 30) | type Context = Context<Self>;
method started (line 32) | fn started(&mut self, ctx: &mut Self::Context) {
type TestIter (line 52) | struct TestIter<F>
function new (line 64) | pub fn new(fn_: F) -> (Self, std::sync::mpsc::Receiver<()>) {
type SystemRunnerHandle (line 71) | pub struct SystemRunnerHandle<F>
function send (line 83) | pub fn send(&self, fn_: F) {
method drop (line 96) | fn drop(&mut self) {
function init_system_runner (line 101) | fn init_system_runner<F>(num_actors: usize) -> SystemRunnerHandle<F>
function init_actors (line 138) | async fn init_actors(num: usize) {
function issue_async_test (line 160) | async fn issue_async_test(num_actors: usize, num_messages: usize) -> () {
function broker_benches (line 180) | fn broker_benches(c: &mut Criterion) {
FILE: actix-broker/examples/actix-web.rs
type Hello (line 9) | struct Hello;
type TestActor (line 11) | struct TestActor;
type Result (line 21) | type Result = ();
method handle (line 22) | fn handle(&mut self, msg: Hello, _ctx: &mut Self::Context) {
type Context (line 14) | type Context = Context<Self>;
method started (line 15) | fn started(&mut self, ctx: &mut Self::Context) {
function index (line 28) | async fn index(_req: HttpRequest) -> Result<HttpResponse, Error> {
function main (line 35) | async fn main() -> io::Result<()> {
FILE: actix-broker/examples/basic.rs
type ActorOne (line 6) | struct ActorOne;
type Result (line 27) | type Result = ();
method handle (line 29) | fn handle(&mut self, msg: MessageTwo, _ctx: &mut Self::Context) {
type ActorTwo (line 7) | struct ActorTwo;
type Result (line 44) | type Result = ();
method handle (line 46) | fn handle(&mut self, msg: MessageOne, _ctx: &mut Self::Context) {
type ActorThree (line 8) | struct ActorThree;
type Result (line 62) | type Result = ();
method handle (line 64) | fn handle(&mut self, msg: MessageOne, _ctx: &mut Self::Context) {
type BrokerType (line 10) | type BrokerType = SystemBroker;
type Context (line 13) | type Context = Context<Self>;
method started (line 15) | fn started(&mut self, ctx: &mut Self::Context) {
type Context (line 35) | type Context = Context<Self>;
method started (line 37) | fn started(&mut self, ctx: &mut Self::Context) {
type Context (line 53) | type Context = Context<Self>;
method started (line 55) | fn started(&mut self, ctx: &mut Self::Context) {
type MessageOne (line 72) | struct MessageOne(String);
type MessageTwo (line 76) | struct MessageTwo(u8);
function main (line 78) | fn main() {
FILE: actix-broker/src/broker.rs
type TypeMap (line 14) | type TypeMap<A> = HashMap<TypeId, A, BuildHasherDefault<AHasher>>;
type Broker (line 17) | pub struct Broker<T> {
type SystemBroker (line 24) | pub struct SystemBroker;
type ArbiterBroker (line 27) | pub struct ArbiterBroker;
function issue_async (line 34) | pub fn issue_async<M: BrokerMsg>(msg: M) {
function issue_async (line 45) | pub fn issue_async<M: BrokerMsg>(msg: M) {
function get_subs (line 53) | fn get_subs<M: BrokerMsg>(
function add_sub (line 73) | fn add_sub<M: BrokerMsg>(&mut self, sub: Recipient<M>, id: TypeId) {
function remove_subs (line 86) | fn remove_subs<M: BrokerMsg>(&mut self, indexes: &[usize]) {
function get_previous_msg (line 100) | fn get_previous_msg<M: BrokerMsg>(&self) -> Option<M> {
function set_msg (line 108) | fn set_msg<M: BrokerMsg>(&mut self, msg: M) {
type Result (line 123) | type Result = ();
function handle (line 125) | fn handle(&mut self, msg: SubscribeAsync<M>, _ctx: &mut Context<Self>) {
type Result (line 132) | type Result = Option<M>;
function handle (line 134) | fn handle(&mut self, msg: SubscribeSync<M>, _ctx: &mut Context<Self>) ->...
type Result (line 142) | type Result = ();
function handle (line 144) | fn handle(&mut self, msg: IssueAsync<M>, _ctx: &mut Context<Self>) {
type Result (line 170) | type Result = ();
function handle (line 172) | fn handle(&mut self, msg: IssueSync<M>, ctx: &mut Context<Self>) {
type Context (line 192) | type Context = Context<Self>;
type RegisteredBroker (line 201) | pub trait RegisteredBroker: 'static + Unpin
method get_broker (line 205) | fn get_broker() -> Addr<Broker<Self>>;
method get_broker (line 209) | fn get_broker() -> Addr<Broker<Self>> {
method get_broker (line 215) | fn get_broker() -> Addr<Broker<Self>> {
FILE: actix-broker/src/issue.rs
type BrokerIssue (line 13) | pub trait BrokerIssue
method issue_async (line 22) | fn issue_async<T: RegisteredBroker, M: BrokerMsg>(&self, msg: M) {
method issue_sync (line 30) | fn issue_sync<T: RegisteredBroker, M: BrokerMsg>(&self, msg: M, ctx: &...
method issue_system_async (line 41) | fn issue_system_async<M: BrokerMsg>(&self, msg: M) {
method issue_system_sync (line 47) | fn issue_system_sync<M: BrokerMsg>(&self, msg: M, ctx: &mut Self::Cont...
method issue_arbiter_async (line 53) | fn issue_arbiter_async<M: BrokerMsg>(&self, msg: M) {
method issue_arbiter_sync (line 59) | fn issue_arbiter_sync<M: BrokerMsg>(&self, msg: M, ctx: &mut Self::Con...
FILE: actix-broker/src/msgs.rs
type BrokerMsg (line 5) | pub trait BrokerMsg: Message<Result = ()> + Send + Clone + 'static {}
type SubscribeAsync (line 11) | pub struct SubscribeAsync<M: BrokerMsg>(pub Recipient<M>, pub TypeId);
type SubscribeSync (line 13) | pub struct SubscribeSync<M: BrokerMsg>(pub Recipient<M>, pub TypeId);
type Result (line 16) | type Result = Option<M>;
type IssueAsync (line 21) | pub struct IssueAsync<M: BrokerMsg>(pub M, pub TypeId);
type IssueSync (line 25) | pub struct IssueSync<M: BrokerMsg>(pub M, pub TypeId);
FILE: actix-broker/src/subscribe.rs
type BrokerSubscribe (line 13) | pub trait BrokerSubscribe
method subscribe_async (line 19) | fn subscribe_async<T: RegisteredBroker, M: BrokerMsg>(&self, ctx: &mut...
method subscribe_sync (line 33) | fn subscribe_sync<T: RegisteredBroker, M: BrokerMsg>(&self, ctx: &mut ...
method subscribe_system_async (line 54) | fn subscribe_system_async<M: BrokerMsg>(&self, ctx: &mut Self::Context)
method subscribe_system_sync (line 64) | fn subscribe_system_sync<M: BrokerMsg>(&self, ctx: &mut Self::Context)
method subscribe_arbiter_async (line 74) | fn subscribe_arbiter_async<M: BrokerMsg>(&self, ctx: &mut Self::Context)
method subscribe_arbiter_sync (line 84) | fn subscribe_arbiter_sync<M: BrokerMsg>(&self, ctx: &mut Self::Context)
FILE: actix-broker/tests/delivery.rs
type TestMessage (line 11) | struct TestMessage;
type TestActor (line 14) | struct TestActor {
type Result (line 27) | type Result = AtomicResponse<Self, ()>;
method handle (line 29) | fn handle(&mut self, _msg: TestMessage, _ctx: &mut Self::Context) -> S...
type Context (line 19) | type Context = Context<Self>;
method started (line 21) | fn started(&mut self, ctx: &mut Self::Context) {
function it_issues_async_on_full_mailbox (line 50) | fn it_issues_async_on_full_mailbox() {
FILE: actix-broker/tests/general.rs
type TestMessageOne (line 11) | struct TestMessageOne(u8);
type TestActorOne (line 13) | struct TestActorOne;
type Result (line 37) | type Result = ();
method handle (line 39) | fn handle(&mut self, msg: TestMessageOne, _ctx: &mut Self::Context) {
type TestActorTwo (line 15) | struct TestActorTwo;
type Result (line 46) | type Result = ();
method handle (line 48) | fn handle(&mut self, msg: TestMessageOne, _ctx: &mut Self::Context) {
type Context (line 18) | type Context = Context<Self>;
method started (line 20) | fn started(&mut self, ctx: &mut Self::Context) {
type Context (line 29) | type Context = Context<Self>;
method started (line 31) | fn started(&mut self, ctx: &mut Self::Context) {
function it_all_works (line 55) | fn it_all_works() {
FILE: actix-derive/src/lib.rs
function message_derive_rtype (line 15) | pub fn message_derive_rtype(input: TokenStream) -> TokenStream {
function message_response_derive_rtype (line 22) | pub fn message_response_derive_rtype(input: TokenStream) -> TokenStream {
function main (line 39) | pub fn main(_: TokenStream, item: TokenStream) -> TokenStream {
function test (line 60) | pub fn test(_: TokenStream, item: TokenStream) -> TokenStream {
FILE: actix-derive/src/message.rs
type AttributeArgs (line 5) | type AttributeArgs = syn::punctuated::Punctuated<syn::Meta, syn::Token![...
constant MESSAGE_ATTR (line 7) | pub const MESSAGE_ATTR: &str = "rtype";
function expand (line 9) | pub fn expand(ast: &syn::DeriveInput) -> TokenStream {
function get_attribute_type_multiple (line 44) | fn get_attribute_type_multiple(
function meta_item_to_ty (line 115) | fn meta_item_to_ty(meta_item: &syn::Meta) -> syn::Result<syn::Type> {
FILE: actix-derive/src/message_response.rs
function expand (line 5) | pub fn expand(ast: &syn::DeriveInput) -> TokenStream {
FILE: actix-derive/tests/test_macro.rs
type Added (line 5) | struct Added(usize);
type Subtracted (line 8) | struct Subtracted(usize);
type Sum (line 12) | struct Sum(usize, usize);
type Difference (line 16) | struct Difference(usize, usize);
type Adder (line 19) | struct Adder;
type Result (line 26) | type Result = <Sum as actix::Message>::Result;
method handle (line 27) | fn handle(&mut self, msg: Sum, _: &mut Self::Context) -> Added {
type Result (line 33) | type Result = <Difference as actix::Message>::Result;
method handle (line 34) | fn handle(&mut self, msg: Difference, _: &mut Self::Context) -> Subtra...
type Context (line 22) | type Context = Context<Self>;
function test_message (line 40) | fn test_message() {
FILE: actix-derive/tests/trybuild.rs
function compile_macros (line 6) | fn compile_macros() {
FILE: actix-derive/tests/trybuild/message-response.rs
type Added (line 4) | struct Added(usize);
function main (line 6) | fn main() {}
FILE: actix-derive/tests/trybuild/message.rs
type Added (line 4) | struct Added(usize);
type Sum (line 8) | struct Sum(usize, usize);
type SumBareType (line 12) | struct SumBareType(usize, usize);
type UnitReturnInString (line 16) | struct UnitReturnInString;
type Adder (line 19) | struct Adder;
type Result (line 26) | type Result = <Sum as actix::Message>::Result;
method handle (line 27) | fn handle(&mut self, msg: Sum, _: &mut Self::Context) -> Added {
type Result (line 33) | type Result = <SumBareType as actix::Message>::Result;
method handle (line 34) | fn handle(&mut self, msg: SumBareType, _: &mut Self::Context) -> Added {
type Context (line 22) | type Context = Context<Self>;
function main (line 40) | async fn main() {
FILE: actix-derive/tests/trybuild/rt-main.rs
function main (line 2) | async fn main() {
FILE: actix/examples/fibonacci.rs
type Fibonacci (line 8) | struct Fibonacci(pub u32);
type Result (line 11) | type Result = Result<u64, ()>;
type SyncActor (line 14) | struct SyncActor;
type Result (line 21) | type Result = Result<u64, ()>;
method handle (line 23) | fn handle(&mut self, msg: Fibonacci, _: &mut Self::Context) -> Self::R...
type Context (line 17) | type Context = SyncContext<Self>;
function main (line 45) | async fn main() {
FILE: actix/examples/mock.rs
type MyActor (line 12) | struct MyActor {}
type Result (line 19) | type Result = ResponseFuture<usize>;
method handle (line 21) | fn handle(&mut self, _msg: Question, _ctx: &mut Context<Self>) -> Self...
type Context (line 15) | type Context = Context<Self>;
type AnsActor (line 29) | struct AnsActor {}
type Result (line 50) | type Result = usize;
method handle (line 52) | fn handle(&mut self, _: Question, _: &mut Context<Self>) -> Self::Resu...
type Question (line 33) | struct Question {}
type AnswerActor (line 36) | type AnswerActor = AnsActor;
type AnswerActor (line 39) | type AnswerActor = Mocker<AnsActor>;
type Context (line 42) | type Context = Context<Self>;
function main (line 58) | async fn main() {
function mocked_behavior (line 69) | async fn mocked_behavior() {
FILE: actix/examples/ping.rs
type Ping (line 4) | struct Ping(usize);
type Result (line 7) | type Result = usize;
type MyActor (line 11) | struct MyActor {
type Result (line 22) | type Result = usize;
method handle (line 24) | fn handle(&mut self, msg: Ping, _: &mut Context<Self>) -> Self::Result {
type Context (line 17) | type Context = Context<Self>;
function main (line 31) | async fn main() {
FILE: actix/examples/ring.rs
type Payload (line 15) | struct Payload(usize);
type Node (line 18) | struct Node {
type Result (line 29) | type Result = ();
method handle (line 31) | fn handle(&mut self, msg: Payload, _: &mut Context<Self>) {
type Context (line 25) | type Context = Context<Self>;
function main (line 58) | fn main() -> io::Result<()> {
function parse_args (line 118) | fn parse_args() -> (usize, usize) {
function print_usage_and_exit (line 146) | fn print_usage_and_exit() -> ! {
FILE: actix/examples/weak_addr.rs
type TimePing (line 14) | pub struct TimePing(Instant);
type RegisterForTime (line 18) | pub struct RegisterForTime(pub WeakAddr<Client>);
type TimeService (line 21) | pub struct TimeService {
method send_tick (line 26) | fn send_tick(&mut self, _ctx: &mut Context<Self>) {
type Result (line 65) | type Result = ();
method handle (line 67) | fn handle(
type Context (line 47) | type Context = Context<Self>;
method started (line 49) | fn started(&mut self, ctx: &mut Self::Context) {
method stopping (line 54) | fn stopping(&mut self, _ctx: &mut Self::Context) -> Running {
method stopped (line 59) | fn stopped(&mut self, _ctx: &mut Self::Context) {
type Client (line 81) | pub struct Client;
type Result (line 106) | type Result = ();
method handle (line 108) | fn handle(&mut self, msg: TimePing, _ctx: &mut Self::Context) -> Self:...
type Context (line 84) | type Context = Context<Self>;
method started (line 86) | fn started(&mut self, ctx: &mut Self::Context) {
method stopping (line 95) | fn stopping(&mut self, _ctx: &mut Self::Context) -> Running {
method stopped (line 100) | fn stopped(&mut self, _ctx: &mut Self::Context) {
function main (line 114) | async fn main() {
FILE: actix/examples/weak_recipient.rs
type TimePing (line 14) | pub struct TimePing(Instant);
type RegisterForTime (line 18) | pub struct RegisterForTime(pub WeakRecipient<TimePing>);
type TimeService (line 21) | pub struct TimeService {
method send_tick (line 26) | fn send_tick(&mut self, _ctx: &mut Context<Self>) {
type Result (line 65) | type Result = ();
method handle (line 67) | fn handle(
type Context (line 47) | type Context = Context<Self>;
method started (line 49) | fn started(&mut self, ctx: &mut Self::Context) {
method stopping (line 54) | fn stopping(&mut self, _ctx: &mut Self::Context) -> Running {
method stopped (line 59) | fn stopped(&mut self, _ctx: &mut Self::Context) {
type ClientA (line 81) | pub struct ClientA;
type Result (line 106) | type Result = ();
method handle (line 108) | fn handle(&mut self, msg: TimePing, _ctx: &mut Self::Context) -> Self:...
type Context (line 84) | type Context = Context<Self>;
method started (line 86) | fn started(&mut self, ctx: &mut Self::Context) {
method stopping (line 95) | fn stopping(&mut self, _ctx: &mut Self::Context) -> Running {
method stopped (line 100) | fn stopped(&mut self, _ctx: &mut Self::Context) {
type ClientB (line 114) | pub struct ClientB;
type Result (line 139) | type Result = ();
method handle (line 141) | fn handle(&mut self, msg: TimePing, _ctx: &mut Self::Context) -> Self:...
type Context (line 117) | type Context = Context<Self>;
method started (line 119) | fn started(&mut self, ctx: &mut Self::Context) {
method stopping (line 128) | fn stopping(&mut self, _ctx: &mut Self::Context) -> Running {
method stopped (line 133) | fn stopped(&mut self, _ctx: &mut Self::Context) {
function main (line 147) | async fn main() {
FILE: actix/src/actor.rs
type Actor (line 75) | pub trait Actor: Sized + Unpin + 'static {
method started (line 80) | fn started(&mut self, ctx: &mut Self::Context) {}
method stopping (line 92) | fn stopping(&mut self, ctx: &mut Self::Context) -> Running {
method stopped (line 101) | fn stopped(&mut self, ctx: &mut Self::Context) {}
method start (line 122) | fn start(self) -> Addr<Self>
method start_default (line 134) | fn start_default() -> Addr<Self>
method start_in_arbiter (line 142) | fn start_in_arbiter<F>(wrk: &ArbiterHandle, f: F) -> Addr<Self>
method create (line 184) | fn create<F>(f: F) -> Addr<Self>
type Supervised (line 209) | pub trait Supervised: Actor {
method restarting (line 211) | fn restarting(&mut self, ctx: &mut <Self as Actor>::Context) {}
type ActorState (line 216) | pub enum ActorState {
method alive (line 235) | pub fn alive(self) -> bool {
method stopping (line 239) | pub fn stopping(self) -> bool {
type Running (line 228) | pub enum Running {
type ActorContext (line 252) | pub trait ActorContext: Sized {
method stop (line 256) | fn stop(&mut self);
method terminate (line 261) | fn terminate(&mut self);
method state (line 264) | fn state(&self) -> ActorState;
type AsyncContext (line 268) | pub trait AsyncContext<A>: ActorContext
method address (line 273) | fn address(&self) -> Addr<A>;
method spawn (line 282) | fn spawn<F>(&mut self, fut: F) -> SpawnHandle
method wait (line 290) | fn wait<F>(&mut self, fut: F)
method waiting (line 295) | fn waiting(&self) -> bool;
method cancel_future (line 300) | fn cancel_future(&mut self, handle: SpawnHandle) -> bool;
method add_stream (line 345) | fn add_stream<S>(&mut self, fut: S) -> SpawnHandle
method add_message_stream (line 390) | fn add_message_stream<S>(&mut self, fut: S)
method notify (line 406) | fn notify<M>(&mut self, msg: M)
method notify_later (line 425) | fn notify_later<M>(&mut self, msg: M, after: Duration) -> SpawnHandle
method run_later (line 443) | fn run_later<F>(&mut self, dur: Duration, f: F) -> SpawnHandle
method run_interval (line 452) | fn run_interval<F>(&mut self, dur: Duration, f: F) -> SpawnHandle
method run_interval_at (line 461) | fn run_interval_at<F>(
type SpawnHandle (line 478) | pub struct SpawnHandle(usize);
method next (line 482) | pub fn next(self) -> SpawnHandle {
method into_usize (line 486) | pub fn into_usize(self) -> usize {
FILE: actix/src/actors/mocker.rs
type Mocker (line 36) | pub struct Mocker<T: Sized + Unpin + 'static> {
function mock (line 43) | pub fn mock(
method default (line 58) | fn default() -> Self {
type Context (line 64) | type Context = Context<Self>;
type Result (line 72) | type Result = M::Result;
function handle (line 73) | fn handle(&mut self, msg: M, ctx: &mut Self::Context) -> M::Result {
FILE: actix/src/address/channel.rs
type Sender (line 32) | pub trait Sender<M>: Send
method do_send (line 37) | fn do_send(&self, msg: M) -> Result<(), SendError<M>>;
method try_send (line 39) | fn try_send(&self, msg: M) -> Result<(), SendError<M>>;
method send (line 41) | fn send(&self, msg: M) -> Result<OneshotReceiver<M::Result>, SendError...
method boxed (line 43) | fn boxed(&self) -> Box<dyn Sender<M> + Sync>;
method hash (line 45) | fn hash(&self) -> usize;
method connected (line 47) | fn connected(&self) -> bool;
method downgrade (line 50) | fn downgrade(&self) -> Box<dyn WeakSender<M> + Sync + 'static>;
function do_send (line 59) | fn do_send(&self, msg: M) -> Result<(), SendError<M>> {
function try_send (line 63) | fn try_send(&self, msg: M) -> Result<(), SendError<M>> {
function send (line 67) | fn send(&self, msg: M) -> Result<OneshotReceiver<<M as Message>::Result>...
function boxed (line 71) | fn boxed(&self) -> Box<dyn Sender<M> + Sync> {
function hash (line 75) | fn hash(&self) -> usize {
function connected (line 79) | fn connected(&self) -> bool {
function downgrade (line 83) | fn downgrade(&self) -> Box<dyn WeakSender<M> + Sync> {
type WeakSender (line 88) | pub trait WeakSender<M>: Send
method upgrade (line 96) | fn upgrade(&self) -> Option<Box<dyn Sender<M> + Sync>>;
method boxed (line 98) | fn boxed(&self) -> Box<dyn WeakSender<M> + Sync>;
type AddressSender (line 104) | pub struct AddressSender<A: Actor> {
function fmt (line 119) | fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
type WeakAddressSender (line 130) | pub struct WeakAddressSender<A: Actor> {
method clone (line 135) | fn clone(&self) -> WeakAddressSender<A> {
function fmt (line 143) | fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
method eq (line 149) | fn eq(&self, other: &Self) -> bool {
type AssertKinds (line 157) | trait AssertKinds: Send + Sync + Clone {}
type AddressReceiver (line 164) | pub struct AddressReceiver<A: Actor> {
type AddressSenderProducer (line 169) | pub struct AddressSenderProducer<A: Actor> {
type Inner (line 173) | struct Inner<A: Actor> {
type State (line 196) | struct State {
method is_closed (line 205) | fn is_closed(&self) -> bool {
constant OPEN_MASK (line 211) | const OPEN_MASK: usize = usize::MAX - (usize::MAX >> 1);
constant INIT_STATE (line 215) | const INIT_STATE: usize = OPEN_MASK;
constant MAX_CAPACITY (line 218) | const MAX_CAPACITY: usize = !(OPEN_MASK);
constant MAX_BUFFER (line 222) | const MAX_BUFFER: usize = MAX_CAPACITY >> 1;
type SenderTask (line 226) | struct SenderTask {
method new (line 232) | fn new() -> Self {
method notify (line 239) | fn notify(&mut self) -> bool {
function channel (line 264) | pub fn channel<A: Actor>(buffer: usize) -> (AddressSender<A>, AddressRec...
function connected (line 296) | pub fn connected(&self) -> bool {
function send (line 306) | pub fn send<M>(&self, msg: M) -> Result<OneshotReceiver<M::Result>, Send...
function try_send (line 346) | pub fn try_send<M>(&self, msg: M, park: bool) -> Result<(), SendError<M>>
function do_send (line 378) | pub fn do_send<M>(&self, msg: M) -> Result<(), SendError<M>>
function downgrade (line 398) | pub fn downgrade(&self) -> WeakAddressSender<A> {
function queue_push_and_signal (line 405) | fn queue_push_and_signal(&self, msg: Envelope<A>) {
function inc_num_messages (line 416) | fn inc_num_messages(&self) -> Option<usize> {
function park (line 440) | fn park(&self) {
function poll_unparked (line 455) | fn poll_unparked(&self, do_park: bool, cx: Option<&mut task::Context<'_>...
function do_send (line 493) | fn do_send(&self, msg: M) -> Result<(), SendError<M>> {
function try_send (line 496) | fn try_send(&self, msg: M) -> Result<(), SendError<M>> {
function send (line 499) | fn send(&self, msg: M) -> Result<OneshotReceiver<M::Result>, SendError<M...
function boxed (line 502) | fn boxed(&self) -> Box<dyn Sender<M> + Sync> {
function hash (line 506) | fn hash(&self) -> usize {
function connected (line 511) | fn connected(&self) -> bool {
function downgrade (line 515) | fn downgrade(&self) -> Box<dyn WeakSender<M> + Sync + 'static> {
method clone (line 523) | fn clone(&self) -> AddressSender<A> {
method drop (line 557) | fn drop(&mut self) {
method eq (line 568) | fn eq(&self, other: &Self) -> bool {
method hash (line 576) | fn hash<H: Hasher>(&self, state: &mut H) {
function upgrade (line 591) | pub fn upgrade(&self) -> Option<AddressSender<A>> {
function upgrade (line 603) | fn upgrade(&self) -> Option<Box<dyn Sender<M> + Sync>> {
function boxed (line 611) | fn boxed(&self) -> Box<dyn WeakSender<M> + Sync> {
function connected (line 623) | pub fn connected(&self) -> bool {
function capacity (line 628) | pub fn capacity(&self) -> usize {
function set_capacity (line 636) | pub fn set_capacity(&mut self, cap: usize) {
function sender (line 649) | pub fn sender(&self) -> AddressSender<A> {
function connected (line 685) | pub fn connected(&self) -> bool {
function capacity (line 690) | pub fn capacity(&self) -> usize {
function set_capacity (line 698) | pub fn set_capacity(&mut self, cap: usize) {
function sender (line 711) | pub fn sender(&self) -> AddressSender<A> {
function sender_producer (line 740) | pub fn sender_producer(&self) -> AddressSenderProducer<A> {
function next_message (line 746) | fn next_message(&mut self) -> Poll<Option<Envelope<A>>> {
function unpark_one (line 780) | fn unpark_one(&mut self) {
function dec_num_messages (line 786) | fn dec_num_messages(&self) {
type Item (line 795) | type Item = Envelope<A>;
method poll_next (line 797) | fn poll_next(self: Pin<&mut Self>, cx: &mut task::Context<'_>) -> Poll<O...
method drop (line 814) | fn drop(&mut self) {
function max_senders (line 857) | fn max_senders(&self) -> usize {
function set_closed (line 862) | fn set_closed(&self) {
function decode_state (line 880) | fn decode_state(num: usize) -> State {
function encode_state (line 887) | fn encode_state(state: &State) -> usize {
type Act (line 904) | struct Act;
type Result (line 915) | type Result = ();
method handle (line 916) | fn handle(&mut self, _: Ping, _: &mut Context<Act>) {}
type Context (line 906) | type Context = Context<Act>;
type Ping (line 909) | struct Ping;
type Result (line 911) | type Result = ();
function test_cap (line 920) | fn test_cap() {
FILE: actix/src/address/envelope.rs
type ToEnvelope (line 10) | pub trait ToEnvelope<A, M: Message>
method pack (line 16) | fn pack(msg: M, tx: Option<Sender<M::Result>>) -> Envelope<A>;
type EnvelopeProxy (line 19) | pub trait EnvelopeProxy<A: Actor> {
method handle (line 21) | fn handle(&mut self, act: &mut A, ctx: &mut A::Context);
function pack (line 30) | fn pack(msg: M, tx: Option<Sender<M::Result>>) -> Envelope<A> {
type Envelope (line 35) | pub struct Envelope<A: Actor>(Box<dyn EnvelopeProxy<A> + Send>);
function new (line 38) | pub fn new<M>(msg: M, tx: Option<Sender<M::Result>>) -> Self
function with_proxy (line 48) | pub fn with_proxy(proxy: Box<dyn EnvelopeProxy<A> + Send>) -> Self {
function handle (line 54) | fn handle(&mut self, act: &mut A, ctx: &mut <A as Actor>::Context) {
type SyncEnvelopeProxy (line 59) | pub struct SyncEnvelopeProxy<M>
function handle (line 75) | fn handle(&mut self, act: &mut A, ctx: &mut <A as Actor>::Context) {
FILE: actix/src/address/message.rs
type Request (line 17) | pub type Request<A, M> = MsgRequest<AddressSender<A>, M>;
type RecipientRequest (line 19) | pub type RecipientRequest<M> = MsgRequest<Box<dyn Sender<M>>, M>;
function new (line 44) | pub(crate) fn new(rx: Option<oneshot::Receiver<M::Result>>, info: Option...
function rx_is_some (line 53) | pub(crate) fn rx_is_some(&self) -> bool {
function timeout (line 58) | pub fn timeout(mut self, dur: Duration) -> Self {
type Output (line 70) | type Output = Result<M::Result, MailboxError>;
method poll (line 72) | fn poll(self: Pin<&mut Self>, cx: &mut task::Context<'_>) -> Poll<Self::...
FILE: actix/src/address/mod.rs
type SendError (line 22) | pub enum SendError<T> {
type MailboxError (line 29) | pub enum MailboxError {
method fmt (line 35) | fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
method fmt (line 41) | fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
function into_inner (line 52) | pub fn into_inner(self) -> T {
function fmt (line 62) | fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
function fmt (line 71) | fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
type Addr (line 80) | pub struct Addr<A: Actor> {
function new (line 85) | pub fn new(tx: AddressSender<A>) -> Addr<A> {
function connected (line 91) | pub fn connected(&self) -> bool {
function do_send (line 100) | pub fn do_send<M>(&self, msg: M)
function try_send (line 114) | pub fn try_send<M>(&self, msg: M) -> Result<(), SendError<M>>
function send (line 129) | pub fn send<M>(&self, msg: M) -> Request<A, M>
function recipient (line 144) | pub fn recipient<M>(self) -> Recipient<M>
function downgrade (line 155) | pub fn downgrade(&self) -> WeakAddr<A> {
method clone (line 163) | fn clone(&self) -> Addr<A> {
method eq (line 171) | fn eq(&self, other: &Self) -> bool {
method hash (line 179) | fn hash<H: Hasher>(&self, state: &mut H) {
function fmt (line 185) | fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
type WeakAddr (line 191) | pub struct WeakAddr<A: Actor> {
function upgrade (line 200) | pub fn upgrade(&self) -> Option<Addr<A>> {
function recipient (line 213) | pub fn recipient<M>(self) -> WeakRecipient<M>
method clone (line 225) | fn clone(&self) -> WeakAddr<A> {
function fmt (line 233) | fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
method eq (line 241) | fn eq(&self, other: &Self) -> bool {
type Recipient (line 252) | pub struct Recipient<M: Message>
function new (line 266) | pub(crate) fn new(tx: Box<dyn Sender<M> + Sync>) -> Recipient<M> {
function do_send (line 274) | pub fn do_send(&self, msg: M) {
function try_send (line 282) | pub fn try_send(&self, msg: M) -> Result<(), SendError<M>> {
function send (line 290) | pub fn send(&self, msg: M) -> RecipientRequest<M> {
function connected (line 298) | pub fn connected(&self) -> bool {
function downgrade (line 303) | pub fn downgrade(&self) -> WeakRecipient<M> {
function from (line 316) | fn from(addr: Addr<A>) -> Self {
method clone (line 326) | fn clone(&self) -> Recipient<M> {
method eq (line 338) | fn eq(&self, other: &Self) -> bool {
method hash (line 355) | fn hash<H: Hasher>(&self, state: &mut H) {
function fmt (line 365) | fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
type WeakRecipient (line 371) | pub struct WeakRecipient<M: Message>
function fmt (line 384) | fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
method clone (line 394) | fn clone(&self) -> Self {
function from (line 406) | fn from(recipient: Recipient<M>) -> Self {
function new (line 416) | pub(crate) fn new(wtx: Box<dyn WeakSender<M> + Sync>) -> WeakRecipient<M> {
function upgrade (line 421) | pub fn upgrade(&self) -> Option<Recipient<M>> {
function from (line 432) | fn from(addr: Addr<A>) -> WeakRecipient<M> {
function from (line 443) | fn from(addr: WeakAddr<A>) -> WeakRecipient<M> {
type ActorWithSmallMailBox (line 457) | struct ActorWithSmallMailBox(Arc<AtomicUsize>);
type Result (line 474) | type Result = <SetCounter as Message>::Result;
method handle (line 476) | fn handle(&mut self, ping: SetCounter, _: &mut Context<Self>) -> Self:...
type Context (line 460) | type Context = Context<Self>;
method started (line 462) | fn started(&mut self, ctx: &mut Self::Context) {
type SetCounter (line 467) | pub struct SetCounter(usize);
type Result (line 470) | type Result = ();
function test_send_over_limit (line 482) | fn test_send_over_limit() {
FILE: actix/src/address/queue.rs
type PopResult (line 54) | pub(super) enum PopResult<T> {
type Node (line 67) | struct Node<T> {
type Queue (line 76) | pub(super) struct Queue<T> {
function new (line 85) | unsafe fn new(v: Option<T>) -> *mut Self {
function new (line 96) | pub(super) fn new() -> Self {
function push (line 105) | pub(super) fn push(&self, t: T) {
function pop (line 125) | pub(super) unsafe fn pop(&self) -> PopResult<T> {
function pop_spin (line 149) | pub(super) unsafe fn pop_spin(&self) -> Option<T> {
method drop (line 174) | fn drop(&mut self) {
FILE: actix/src/context.rs
type Context (line 12) | pub struct Context<A>
function fmt (line 21) | fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
method stop (line 34) | fn stop(&mut self) {
method terminate (line 38) | fn terminate(&mut self) {
method state (line 42) | fn state(&self) -> ActorState {
function spawn (line 52) | fn spawn<F>(&mut self, fut: F) -> SpawnHandle
function wait (line 60) | fn wait<F>(&mut self, fut: F)
function waiting (line 68) | fn waiting(&self) -> bool {
function cancel_future (line 73) | fn cancel_future(&mut self, handle: SpawnHandle) -> bool {
function address (line 78) | fn address(&self) -> Addr<A> {
function new (line 127) | pub fn new() -> Self {
function with_receiver (line 136) | pub fn with_receiver(rx: AddressReceiver<A>) -> Self {
function run (line 145) | pub fn run(self, act: A) -> Addr<A> {
function into_future (line 152) | pub fn into_future(mut self, act: A) -> ContextFut<A, Self> {
function handle (line 161) | pub fn handle(&self) -> SpawnHandle {
function set_mailbox_capacity (line 187) | pub fn set_mailbox_capacity(&mut self, cap: usize) {
function connected (line 192) | pub fn connected(&self) -> bool {
method default (line 202) | fn default() -> Self {
function parts (line 211) | fn parts(&mut self) -> &mut ContextParts<A> {
type ContextFutureSpawner (line 217) | pub trait ContextFutureSpawner<A>
method spawn (line 223) | fn spawn(self, ctx: &mut A::Context);
method wait (line 230) | fn wait(self, ctx: &mut A::Context);
method spawn (line 240) | fn spawn(self, ctx: &mut A::Context) {
method wait (line 245) | fn wait(self, ctx: &mut A::Context) {
FILE: actix/src/context_impl.rs
type Item (line 32) | type Item<A> = (SpawnHandle, Pin<Box<dyn ActorFuture<A, Output = ()>>>);
type AsyncContextParts (line 34) | pub trait AsyncContextParts<A>: ActorContext + AsyncContext<A>
method parts (line 38) | fn parts(&mut self) -> &mut ContextParts<A>;
type ContextParts (line 41) | pub struct ContextParts<A>
function fmt (line 58) | fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
function new (line 72) | pub fn new(addr: AddressSenderProducer<A>) -> Self {
function stop (line 87) | pub fn stop(&mut self) {
function terminate (line 96) | pub fn terminate(&mut self) {
function state (line 102) | pub fn state(&self) -> ActorState {
function waiting (line 116) | pub fn waiting(&self) -> bool {
function curr_handle (line 125) | pub fn curr_handle(&self) -> SpawnHandle {
function spawn (line 131) | pub fn spawn<F>(&mut self, fut: F) -> SpawnHandle
function wait (line 146) | pub fn wait<F>(&mut self, f: F)
function cancel_future (line 155) | pub fn cancel_future(&mut self, handle: SpawnHandle) -> bool {
function capacity (line 161) | pub fn capacity(&mut self) -> usize {
function set_mailbox_capacity (line 166) | pub fn set_mailbox_capacity(&mut self, cap: usize) {
function address (line 172) | pub fn address(&self) -> Addr<A> {
function restart (line 181) | pub(crate) fn restart(&mut self) {
function started (line 189) | pub fn started(&mut self) -> bool {
function connected (line 195) | pub fn connected(&self) -> bool {
type ContextFut (line 200) | pub struct ContextFut<A, C>
function fmt (line 217) | fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
method drop (line 227) | fn drop(&mut self) {
function new (line 242) | pub fn new(ctx: C, act: A, mailbox: Mailbox<A>) -> Self {
function ctx (line 253) | pub fn ctx(&mut self) -> &mut C {
function address (line 258) | pub fn address(&self) -> Addr<A> {
function stopping (line 263) | fn stopping(&mut self) -> bool {
function alive (line 271) | pub fn alive(&mut self) -> bool {
function restart (line 295) | pub fn restart(&mut self) -> bool
function merge (line 310) | fn merge(&mut self) -> bool {
function clean_canceled_handle (line 334) | fn clean_canceled_handle(&mut self) {
type Output (line 370) | type Output = ();
method poll (line 372) | fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
FILE: actix/src/context_items.rs
type ActorWaitItem (line 18) | pub(crate) struct ActorWaitItem<A: Actor>(Pin<Box<dyn ActorFuture<A, Out...
function new (line 26) | pub fn new<F>(fut: F) -> Self
function poll (line 33) | pub fn poll(
function new (line 61) | pub fn new(msg: M, timeout: Duration) -> Self {
type Output (line 75) | type Output = ();
function poll (line 77) | fn poll(
type ActorMessageItem (line 91) | pub(crate) struct ActorMessageItem<M: Message> {
function new (line 98) | pub fn new(msg: M) -> Self {
type Output (line 109) | type Output = ();
function poll (line 111) | fn poll(
function new (line 132) | pub fn new(st: S) -> Self {
type Output (line 144) | type Output = ();
function poll (line 146) | fn poll(
FILE: actix/src/fut/future/either.rs
type Output (line 16) | type Output = A::Output;
function poll (line 18) | fn poll(
FILE: actix/src/fut/future/map.rs
function new (line 28) | pub(super) fn new(future: Fut, f: F) -> Self {
type Output (line 39) | type Output = U;
function poll (line 41) | fn poll(
FILE: actix/src/fut/future/mod.rs
type ActorFuture (line 113) | pub trait ActorFuture<A: Actor> {
method poll (line 117) | fn poll(
type ActorFutureExt (line 125) | pub trait ActorFutureExt<A: Actor>: ActorFuture<A> {
method map (line 128) | fn map<F, U>(self, f: F) -> Map<Self, F>
method then (line 138) | fn then<F, Fut>(self, f: F) -> Then<Self, Fut, F>
method timeout (line 150) | fn timeout(self, timeout: Duration) -> Timeout<Self>
method boxed_local (line 160) | fn boxed_local(self) -> LocalBoxActorFuture<A, Self::Output>
type LocalBoxActorFuture (line 176) | pub type LocalBoxActorFuture<A, I> = Pin<Box<dyn ActorFuture<A, Output =...
type Output (line 183) | type Output = F::Output;
function poll (line 185) | fn poll(
type Output (line 201) | type Output = <<P as Deref>::Target as ActorFuture<A>>::Output;
function poll (line 203) | fn poll(
type WrapFuture (line 214) | pub trait WrapFuture<A>
method actfuture (line 223) | fn actfuture(self) -> Self::Future;
method into_actor (line 226) | fn into_actor(self, a: &A) -> Self::Future;
type Future (line 230) | type Future = FutureWrap<F, A>;
method actfuture (line 233) | fn actfuture(self) -> Self::Future {
method into_actor (line 237) | fn into_actor(self, _: &A) -> Self::Future {
function wrap_future (line 259) | pub fn wrap_future<F, A>(f: F) -> FutureWrap<F, A>
type Output (line 275) | type Output = F::Output;
function poll (line 277) | fn poll(
FILE: actix/src/fut/future/result.rs
function result (line 33) | pub fn result<T, E>(r: Result<T, E>) -> Ready<Result<T, E>> {
function ok (line 56) | pub fn ok<T, E>(t: T) -> Ready<Result<T, E>> {
function err (line 77) | pub fn err<T, E>(e: E) -> Ready<Result<T, E>> {
type Output (line 85) | type Output = T;
function poll (line 88) | fn poll(
FILE: actix/src/fut/future/then.rs
function new (line 33) | pub(super) fn new<A, B, F, Act>(future: A, f: F) -> Then<A, B, F>
type Output (line 52) | type Output = B::Output;
function poll (line 54) | fn poll(
FILE: actix/src/fut/future/timeout.rs
function new (line 32) | pub(super) fn new(future: F, timeout: Duration) -> Self {
type Output (line 45) | type Output = Result<F::Output, ()>;
function poll (line 47) | fn poll(
FILE: actix/src/fut/stream/collect.rs
function new (line 28) | pub(super) fn new(stream: S) -> Self {
type Output (line 42) | type Output = C;
function poll (line 44) | fn poll(
FILE: actix/src/fut/stream/finish.rs
function new (line 25) | pub fn new(stream: S) -> Finish<S> {
type Output (line 35) | type Output = ();
function poll (line 37) | fn poll(
FILE: actix/src/fut/stream/fold.rs
function new (line 28) | pub(super) fn new<S, A, F, Fut>(stream: S, f: F, t: Fut::Output) -> Fold...
type Output (line 50) | type Output = Fut::Output;
function poll (line 52) | fn poll(
FILE: actix/src/fut/stream/map.rs
function new (line 22) | pub(super) fn new<S, A, F, U>(stream: S, f: F) -> Map<S, F>
type Item (line 37) | type Item = U;
function poll_next (line 39) | fn poll_next(
FILE: actix/src/fut/stream/mod.rs
type ActorStream (line 34) | pub trait ActorStream<A: Actor> {
method poll_next (line 38) | fn poll_next(
type ActorStreamExt (line 46) | pub trait ActorStreamExt<A: Actor>: ActorStream<A> {
method map (line 57) | fn map<F, U>(self, f: F) -> Map<Self, F>
method then (line 74) | fn then<F, Fut>(self, f: F) -> Then<Self, F, Fut>
method fold (line 91) | fn fold<F, Fut>(self, init: Fut::Output, f: F) -> Fold<Self, F, Fut, F...
method take_while (line 106) | fn take_while<F, Fut>(self, f: F) -> TakeWhile<Self, Self::Item, F, Fut>
method skip_while (line 122) | fn skip_while<F, Fut>(self, f: F) -> SkipWhile<Self, Self::Item, F, Fut>
method timeout (line 134) | fn timeout(self, timeout: Duration) -> Timeout<Self>
method collect (line 145) | fn collect<C>(self) -> Collect<Self, C>
method finish (line 154) | fn finish(self) -> Finish<Self>
type WrapStream (line 170) | pub trait WrapStream<A>
method actstream (line 179) | fn actstream(self) -> Self::Stream;
method into_actor (line 182) | fn into_actor(self, a: &A) -> Self::Stream;
type Stream (line 190) | type Stream = StreamWrap<S, A>;
method actstream (line 193) | fn actstream(self) -> Self::Stream {
method into_actor (line 197) | fn into_actor(self, _: &A) -> Self::Stream {
function wrap_stream (line 215) | pub fn wrap_stream<S, A>(stream: S) -> StreamWrap<S, A>
type Item (line 231) | type Item = S::Item;
function poll_next (line 233) | fn poll_next(
FILE: actix/src/fut/stream/skip_while.rs
function new (line 29) | pub(super) fn new<S, A, F, Fut>(stream: S, f: F) -> SkipWhile<S, S::Item...
type Item (line 52) | type Item = S::Item;
function poll_next (line 54) | fn poll_next(
FILE: actix/src/fut/stream/take_while.rs
function new (line 29) | pub(super) fn new<S, A, F, Fut>(stream: S, f: F) -> TakeWhile<S, S::Item...
type Item (line 52) | type Item = S::Item;
function poll_next (line 54) | fn poll_next(
FILE: actix/src/fut/stream/then.rs
function new (line 27) | pub(super) fn new<S, A, F, Fut>(stream: S, f: F) -> Then<S, F, Fut>
type Item (line 48) | type Item = Fut::Output;
function poll_next (line 50) | fn poll_next(
FILE: actix/src/fut/stream/timeout.rs
function new (line 31) | pub(super) fn new(stream: S, timeout: Duration) -> Self {
type Item (line 46) | type Item = Result<S::Item, ()>;
function poll_next (line 48) | fn poll_next(
FILE: actix/src/fut/try_future/and_then.rs
function new (line 36) | pub(super) fn new<A, B, F, Act>(future: A, f: F) -> AndThen<A, B, F>
type Output (line 55) | type Output = Result<B::Ok, A::Error>;
function poll (line 57) | fn poll(
FILE: actix/src/fut/try_future/map_err.rs
function new (line 31) | pub(crate) fn new(future: Fut, f: F) -> Self {
type Output (line 42) | type Output = Result<Fut::Ok, U>;
function poll (line 44) | fn poll(
FILE: actix/src/fut/try_future/map_ok.rs
function new (line 31) | pub(crate) fn new(future: Fut, f: F) -> Self {
type Output (line 42) | type Output = Result<U, Fut::Error>;
function poll (line 44) | fn poll(
FILE: actix/src/fut/try_future/mod.rs
type Sealed (line 19) | pub trait Sealed<A> {}
type ActorTryFuture (line 31) | pub trait ActorTryFuture<A: Actor>: ActorFuture<A> + private_try_act_fut...
method try_poll (line 43) | fn try_poll(
type Ok (line 56) | type Ok = T;
type Error (line 57) | type Error = E;
method try_poll (line 59) | fn try_poll(
type ActorTryFutureExt (line 70) | pub trait ActorTryFutureExt<A: Actor>: ActorTryFuture<A> {
method and_then (line 83) | fn and_then<Fut, F>(self, f: F) -> AndThen<Self, Fut, F>
method map_ok (line 105) | fn map_ok<T, F>(self, f: F) -> MapOk<Self, F>
method map_err (line 125) | fn map_err<T, F>(self, f: F) -> MapErr<Self, F>
FILE: actix/src/handler.rs
type Handler (line 18) | pub trait Handler<M>
method handle (line 30) | fn handle(&mut self, msg: M, ctx: &mut Self::Context) -> Self::Result;
type Message (line 34) | pub trait Message {
type Result (line 45) | type Result = M::Result;
type Result (line 53) | type Result = M::Result;
type MessageResult (line 82) | pub struct MessageResult<M: Message>(pub M::Result);
type AtomicResponse (line 137) | pub struct AtomicResponse<A, T>(ResponseActFuture<A, T>);
function new (line 140) | pub fn new(fut: ResponseActFuture<A, T>) -> Self {
function handle (line 151) | fn handle(self, ctx: &mut A::Context, tx: Option<OneshotSender<M::Result...
type ResponseActFuture (line 200) | pub type ResponseActFuture<A, I> = LocalBoxActorFuture<A, I>;
type ResponseFuture (line 234) | pub type ResponseFuture<I> = Pin<Box<dyn Future<Output = I>>>;
type MessageResponse (line 253) | pub trait MessageResponse<A: Actor, M: Message> {
method handle (line 254) | fn handle(self, ctx: &mut A::Context, tx: Option<OneshotSender<M::Resu...
function handle (line 262) | fn handle(self, _: &mut A::Context, tx: Option<OneshotSender<M::Result>>) {
function handle (line 274) | fn handle(self, _: &mut A::Context, tx: Option<OneshotSender<Self>>) {
function handle (line 285) | fn handle(self, _: &mut A::Context, tx: Option<OneshotSender<Self>>) {
function handle (line 296) | fn handle(self, _: &mut A::Context, tx: Option<OneshotSender<Self>>) {
function handle (line 307) | fn handle(self, _: &mut A::Context, tx: Option<OneshotSender<Self>>) {
function handle (line 318) | fn handle(self, _: &mut A::Context, tx: Option<OneshotSender<Self>>) {
function handle (line 329) | fn handle(self, ctx: &mut A::Context, tx: Option<OneshotSender<M::Result...
function handle (line 395) | fn handle(self, _: &mut A::Context, tx: Option<OneshotSender<M::Result>>) {
type ResponseTypeItem (line 400) | enum ResponseTypeItem<I> {
type Response (line 406) | pub struct Response<I> {
function fmt (line 411) | fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
function fut (line 423) | pub fn fut<T>(fut: T) -> Self
function reply (line 433) | pub fn reply(val: I) -> Self {
function handle (line 445) | fn handle(self, _: &mut A::Context, tx: Option<OneshotSender<M::Result>>) {
type ActorResponseTypeItem (line 455) | enum ActorResponseTypeItem<A, I> {
type ActorResponse (line 461) | pub struct ActorResponse<A, I> {
function fmt (line 466) | fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
function reply (line 478) | pub fn reply(val: I) -> Self {
function r#async (line 485) | pub fn r#async<T>(fut: T) -> Self
function handle (line 501) | fn handle(self, ctx: &mut A::Context, tx: Option<OneshotSender<M::Result...
function from (line 513) | fn from(fut: Pin<Box<dyn ActorFuture<A, Output = I>>>) -> Self {
type OneshotSend (line 552) | trait OneshotSend<M> {
method send (line 553) | fn send(self, msg: M);
function send (line 557) | fn send(self, msg: M) {
FILE: actix/src/io.rs
type WriteHandler (line 29) | pub trait WriteHandler<E>
method error (line 38) | fn error(&mut self, err: E, ctx: &mut Self::Context) -> Running {
method finished (line 45) | fn finished(&mut self, ctx: &mut Self::Context) {
constant LOW_WATERMARK (line 57) | const LOW_WATERMARK: usize = 4 * 1024;
constant HIGH_WATERMARK (line 58) | const HIGH_WATERMARK: usize = 4 * LOW_WATERMARK;
type Writer (line 61) | pub struct Writer<T: AsyncWrite, E: From<io::Error>> {
type UnsafeWriter (line 65) | struct UnsafeWriter<T: AsyncWrite, E: From<io::Error>>(Rc<RefCell<InnerW...
method clone (line 68) | fn clone(&self) -> Self {
type InnerWriter (line 73) | struct InnerWriter<E: From<io::Error>> {
function new (line 84) | pub fn new<A, C>(io: T, ctx: &mut C) -> Self
function close (line 114) | pub fn close(&mut self) {
function closed (line 119) | pub fn closed(&self) -> bool {
function set_buffer_capacity (line 124) | pub fn set_buffer_capacity(&mut self, low_watermark: usize, high_waterma...
function write (line 131) | pub fn write(&mut self, msg: &[u8]) {
function handle (line 140) | pub fn handle(&self) -> SpawnHandle {
type WriterFut (line 145) | struct WriterFut<T, E>
type Output (line 160) | type Output = ();
function poll (line 162) | fn poll(
type WriterDrain (line 242) | struct WriterDrain<T, E>
type Output (line 257) | type Output = ();
function poll (line 259) | fn poll(
type FramedWrite (line 306) | pub struct FramedWrite<I, T: AsyncWrite + Unpin, U: Encoder<I>> {
function new (line 312) | pub fn new<A, C>(io: T, enc: U, ctx: &mut C) -> Self
function from_buffer (line 340) | pub fn from_buffer<A, C>(io: T, enc: U, buffer: BytesMut, ctx: &mut C) -...
function close (line 371) | pub fn close(&mut self) {
function closed (line 376) | pub fn closed(&self) -> bool {
function set_buffer_capacity (line 381) | pub fn set_buffer_capacity(&mut self, low: usize, high: usize) {
function write (line 388) | pub fn write(&mut self, item: I) {
function handle (line 399) | pub fn handle(&self) -> SpawnHandle {
method drop (line 405) | fn drop(&mut self) {
type SinkWrite (line 418) | pub struct SinkWrite<I, S: Sink<I> + Unpin> {
function new (line 423) | pub fn new<A, C>(sink: S, ctxt: &mut C) -> Self
function write (line 448) | pub fn write(&mut self, item: I) -> Result<(), I> {
function close (line 461) | pub fn close(&mut self) {
function closed (line 467) | pub fn closed(&self) -> bool {
function notify_task (line 471) | fn notify_task(&self) {
function handle (line 478) | pub fn handle(&self) -> SpawnHandle {
type InnerSinkWrite (line 483) | struct InnerSinkWrite<I, S: Sink<I>> {
type SinkWriteFuture (line 495) | struct SinkWriteFuture<I: 'static, S: Sink<I>> {
type Output (line 505) | type Output = ();
function poll (line 507) | fn poll(
FILE: actix/src/lib.rs
function run (line 176) | pub fn run<R>(f: R) -> std::io::Result<()>
FILE: actix/src/mailbox.rs
constant DEFAULT_CAPACITY (line 11) | pub const DEFAULT_CAPACITY: usize = 16;
type Mailbox (line 13) | pub struct Mailbox<A>
function fmt (line 26) | fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
method default (line 39) | fn default() -> Self {
function new (line 51) | pub fn new(msgs: AddressReceiver<A>) -> Self {
function capacity (line 55) | pub fn capacity(&self) -> usize {
function set_capacity (line 59) | pub fn set_capacity(&mut self, cap: usize) {
function connected (line 64) | pub fn connected(&self) -> bool {
function address (line 68) | pub fn address(&self) -> Addr<A> {
function sender_producer (line 72) | pub fn sender_producer(&self) -> AddressSenderProducer<A> {
function poll (line 76) | pub fn poll(&mut self, act: &mut A, ctx: &mut A::Context, task: &mut tas...
FILE: actix/src/registry.rs
type AnyMap (line 24) | type AnyMap = HashMap<TypeId, Box<dyn Any>>;
type Registry (line 88) | pub struct Registry {
method get (line 127) | pub fn get<A: ArbiterService + Actor<Context = Context<A>>>(&self) -> ...
method get_or_start_default (line 134) | pub fn get_or_start_default<A: ArbiterService + Actor<Context = Contex...
method try_get (line 147) | pub fn try_get<A: Actor<Context = Context<A>>>(&self) -> Option<Addr<A...
method query (line 160) | pub fn query<A: Actor<Context = Context<A>>>(&self) -> Option<Addr<A>> {
method set (line 177) | pub fn set<A: Actor<Context = Context<A>>>(addr: Addr<A>) {
type ArbiterService (line 102) | pub trait ArbiterService: Actor<Context = Context<Self>> + Supervised + ...
method start_service (line 104) | fn start_service() -> Addr<Self> {
method service_started (line 113) | fn service_started(&mut self, ctx: &mut Context<Self>) {}
method from_registry (line 116) | fn from_registry() -> Addr<Self> {
type SystemRegistry (line 246) | pub struct SystemRegistry {
method new (line 291) | pub(crate) fn new(system: ArbiterHandle) -> Self {
method get (line 300) | pub fn get<A: SystemService + Actor<Context = Context<A>>>(&mut self) ...
method query (line 315) | pub fn query<A: SystemService + Actor<Context = Context<A>>>(&self) ->...
method set (line 327) | pub fn set<A: SystemService + Actor<Context = Context<A>>>(addr: Addr<...
type SystemService (line 255) | pub trait SystemService: Actor<Context = Context<Self>> + Supervised + D...
method start_service (line 257) | fn start_service(wrk: &ArbiterHandle) -> Addr<Self> {
method service_started (line 266) | fn service_started(&mut self, ctx: &mut Context<Self>) {}
method from_registry (line 269) | fn from_registry() -> Addr<Self> {
FILE: actix/src/stream.rs
type StreamHandler (line 59) | pub trait StreamHandler<I>
method handle (line 64) | fn handle(&mut self, item: I, ctx: &mut Self::Context);
method started (line 69) | fn started(&mut self, ctx: &mut Self::Context) {}
method finished (line 74) | fn finished(&mut self, ctx: &mut Self::Context) {
method add_stream (line 79) | fn add_stream<S>(stream: S, ctx: &mut Self::Context) -> SpawnHandle
function new (line 103) | pub fn new(fut: S) -> Self {
type Output (line 117) | type Output = ();
function poll (line 119) | fn poll(
FILE: actix/src/supervisor.rs
function start (line 110) | pub fn start<F>(f: F) -> Addr<A>
function start_in_arbiter (line 128) | pub fn start_in_arbiter<F>(sys: &ArbiterHandle, f: F) -> Addr<A>
type Output (line 152) | type Output = ();
method poll (line 154) | fn poll(self: Pin<&mut Self>, cx: &mut task::Context<'_>) -> Poll<Self::...
FILE: actix/src/sync.rs
type SyncArbiter (line 94) | pub struct SyncArbiter<A>
function start (line 110) | pub fn start<F>(threads: usize, factory: F) -> Addr<A>
function start_with_thread_builder (line 123) | pub fn start_with_thread_builder<F, BF>(
type Context (line 163) | type Context = Context<Self>;
type Output (line 171) | type Output = ();
method poll (line 173) | fn poll(self: Pin<&mut Self>, cx: &mut task::Context<'_>) -> Poll<Self::...
function pack (line 204) | fn pack(msg: M, tx: Option<SyncSender<M::Result>>) -> Envelope<A> {
type SyncContext (line 238) | pub struct SyncContext<A>
function new (line 254) | fn new(
function run (line 270) | fn run(&mut self) {
function address (line 310) | pub fn address(&self) -> Addr<A> {
method stop (line 321) | fn stop(&mut self) {
method terminate (line 328) | fn terminate(&mut self) {
method state (line 334) | fn state(&self) -> ActorState {
type SyncContextEnvelope (line 339) | pub(crate) struct SyncContextEnvelope<M>
function new (line 352) | pub fn new(msg: M, tx: Option<SyncSender<M::Result>>) -> Self {
function handle (line 363) | fn handle(&mut self, act: &mut A, ctx: &mut A::Context) {
type SyncActor2 (line 381) | struct SyncActor2;
type Result (line 414) | type Result = ();
method handle (line 416) | fn handle(&mut self, msg: Msg, _: &mut Self::Context) -> Self::Result {
type Context (line 384) | type Context = SyncContext<Self>;
type SyncActor1 (line 387) | struct SyncActor1(Addr<SyncActor2>);
method run (line 394) | fn run() -> SyncActor1 {
type Result (line 406) | type Result = ();
method handle (line 408) | fn handle(&mut self, msg: Msg, _: &mut Self::Context) -> Self::Result {
type Context (line 390) | type Context = SyncContext<Self>;
type Msg (line 399) | struct Msg(oneshot::Sender<u8>);
type Result (line 402) | type Result = ();
function nested_sync_arbiters (line 422) | fn nested_sync_arbiters() {
FILE: actix/src/utils.rs
type Condition (line 25) | pub struct Condition<T>
function wait (line 37) | pub fn wait(&mut self) -> oneshot::Receiver<T> {
function set (line 43) | pub fn set(self, result: T) {
method default (line 55) | fn default() -> Self {
function new (line 108) | pub fn new<F>(timeout: Duration, f: F) -> TimerFunc<A>
type Output (line 123) | type Output = ();
function poll (line 125) | fn poll(
function new (line 189) | pub fn new<F>(interval: Duration, task: F) -> IntervalFunc<A>
function new_at (line 202) | pub fn new_at<F>(start: Instant, interval: Duration, task: F) -> Interva...
type Item (line 215) | type Item = ();
function poll_next (line 217) | fn poll_next(
FILE: actix/tests/derive.rs
type Empty (line 9) | struct Empty;
type EmptyActor (line 11) | struct EmptyActor;
type Result (line 18) | type Result = ();
method handle (line 20) | fn handle(&mut self, _message: Empty, _context: &mut Context<Self>) {}
type Context (line 14) | type Context = Context<Self>;
function response_derive_empty (line 25) | fn response_derive_empty() {
type SumResult (line 43) | struct SumResult(usize, usize);
type SumResultActor (line 45) | struct SumResultActor;
type Result (line 52) | type Result = Result<usize, ()>;
method handle (line 54) | fn handle(&mut self, message: SumResult, _context: &mut Context<Self>)...
type Context (line 48) | type Context = Context<Self>;
function derive_result (line 60) | pub fn derive_result() {
type SumOne (line 78) | struct SumOne(usize, usize);
type SumOneActor (line 80) | struct SumOneActor;
type Result (line 87) | type Result = usize;
method handle (line 89) | fn handle(&mut self, message: SumOne, _context: &mut Context<Self>) ->...
type Context (line 83) | type Context = Context<Self>;
function response_derive_one (line 95) | pub fn response_derive_one() {
type MulRes (line 112) | struct MulRes(usize);
type MulOne (line 116) | struct MulOne(usize, usize);
type MulOneActor (line 118) | struct MulOneActor;
type Result (line 125) | type Result = MulRes;
method handle (line 127) | fn handle(&mut self, message: MulOne, _context: &mut Context<Self>) ->...
type Context (line 121) | type Context = Context<Self>;
function derive_response_one (line 133) | pub fn derive_response_one() {
type MulAny (line 150) | struct MulAny<T: 'static + Mul>(T);
type MulAnyOne (line 154) | struct MulAnyOne(usize, usize);
type MulAnyOneActor (line 156) | struct MulAnyOneActor;
type Result (line 163) | type Result = MulAny<usize>;
method handle (line 165) | fn handle(&mut self, message: MulAnyOne, _context: &mut Context<Self>)...
type Context (line 159) | type Context = Context<Self>;
function derive_response_two (line 171) | pub fn derive_response_two() {
FILE: actix/tests/test_actor.rs
type Num (line 16) | struct Num(usize);
type Result (line 19) | type Result = ();
type MyActor (line 22) | struct MyActor(Arc<AtomicUsize>, Arc<AtomicBool>);
method handle (line 34) | fn handle(&mut self, msg: Num, _: &mut Context<MyActor>) {
method finished (line 38) | fn finished(&mut self, _: &mut Context<MyActor>) {
type Context (line 25) | type Context = actix::Context<Self>;
method stopping (line 27) | fn stopping(&mut self, _: &mut Self::Context) -> Running {
function test_stream (line 44) | async fn test_stream() {
type Stop (line 65) | struct Stop;
type StopOnRequest (line 67) | struct StopOnRequest(Arc<AtomicUsize>, Arc<AtomicBool>, Arc<AtomicBool>);
method handle (line 74) | fn handle(&mut self, msg: Num, _: &mut Self::Context) {
method finished (line 78) | fn finished(&mut self, _: &mut Self::Context) {
type Result (line 84) | type Result = ();
method handle (line 86) | fn handle(&mut self, _: Stop, ctx: &mut Self::Context) {
type Context (line 70) | type Context = actix::Context<Self>;
function test_infinite_stream (line 93) | async fn test_infinite_stream() {
type MySyncActor (line 125) | struct MySyncActor {
type Result (line 152) | type Result = ();
method handle (line 154) | fn handle(&mut self, msg: Num, ctx: &mut Self::Context) {
type Context (line 134) | type Context = actix::SyncContext<Self>;
method started (line 136) | fn started(&mut self, _: &mut Self::Context) {
method stopping (line 139) | fn stopping(&mut self, _: &mut Self::Context) -> Running {
method stopped (line 143) | fn stopped(&mut self, _: &mut Self::Context) {
function test_restart_sync_actor (line 163) | fn test_restart_sync_actor() {
type IntervalActor (line 200) | struct IntervalActor {
method new (line 207) | pub fn new(elapses_left: usize, sender: mpsc::Sender<Instant>) -> Self {
type Context (line 218) | type Context = actix::Context<Self>;
method started (line 220) | fn started(&mut self, ctx: &mut Self::Context) {
function test_run_interval (line 237) | fn test_run_interval() {
type IntervalAtActor (line 257) | struct IntervalAtActor {
method new (line 264) | pub fn new(elapses_left: usize, sender: mpsc::Sender<Instant>) -> Self {
type Context (line 275) | type Context = actix::Context<Self>;
method started (line 277) | fn started(&mut self, ctx: &mut Self::Context) {
function test_run_interval_at (line 299) | fn test_run_interval_at() {
FILE: actix/tests/test_address.rs
type Ping (line 14) | struct Ping;
type Result (line 17) | type Result = ();
type MyActor (line 20) | struct MyActor(Arc<AtomicUsize>);
type Result (line 27) | type Result = ();
method handle (line 29) | fn handle(&mut self, _: Ping, _: &mut Self::Context) {
type Context (line 23) | type Context = actix::Context<Self>;
type MyActor3 (line 35) | struct MyActor3;
type Result (line 42) | type Result = ();
method handle (line 44) | fn handle(&mut self, _: Ping, _: &mut actix::Context<MyActor3>) -> Sel...
type Context (line 38) | type Context = Context<Self>;
type PingCounterActor (line 50) | struct PingCounterActor {
type Result (line 73) | type Result = ();
method handle (line 75) | fn handle(&mut self, _msg: Ping, _ctx: &mut Self::Context) -> Self::Re...
type Result (line 81) | type Result = <CountPings as actix::Message>::Result;
method handle (line 83) | fn handle(&mut self, _msg: CountPings, _ctx: &mut Self::Context) -> Se...
method default (line 55) | fn default() -> Self {
type Context (line 63) | type Context = Context<Self>;
type CountPings (line 66) | struct CountPings;
type Result (line 69) | type Result = usize;
function test_address (line 89) | fn test_address() {
type WeakAddressRunner (line 118) | struct WeakAddressRunner;
type Context (line 121) | type Context = Context<Self>;
method started (line 123) | fn started(&mut self, ctx: &mut Self::Context) {
function test_weak_address (line 147) | fn test_weak_address() {
type WeakRecipientRunner (line 157) | struct WeakRecipientRunner;
type Context (line 160) | type Context = Context<Self>;
method started (line 162) | fn started(&mut self, ctx: &mut Self::Context) {
function test_weak_recipient (line 193) | fn test_weak_recipient() {
function test_weak_recipient_can_be_cloned (line 204) | fn test_weak_recipient_can_be_cloned() {
function test_recipient_can_be_downgraded (line 233) | fn test_recipient_can_be_downgraded() {
function test_weak_addr_partial_equality (line 265) | fn test_weak_addr_partial_equality() {
function test_sync_recipient_call (line 312) | fn test_sync_recipient_call() {
function test_error_result (line 335) | fn test_error_result() {
type TimeoutActor (line 349) | struct TimeoutActor;
type Result (line 356) | type Result = ();
method handle (line 358) | fn handle(&mut self, _: Ping, ctx: &mut Self::Context) {
type Context (line 352) | type Context = actix::Context<Self>;
function test_message_timeout (line 364) | fn test_message_timeout() {
type TimeoutActor3 (line 391) | struct TimeoutActor3(Addr<TimeoutActor>, Arc<AtomicUsize>);
type Context (line 394) | type Context = Context<Self>;
method started (line 396) | fn started(&mut self, ctx: &mut Self::Context) {
function test_call_message_timeout (line 418) | fn test_call_message_timeout() {
function test_address_eq (line 434) | fn test_address_eq() {
function test_address_hash (line 455) | fn test_address_hash() {
function test_recipient_eq (line 490) | fn test_recipient_eq() {
function test_recipient_hash (line 514) | fn test_recipient_hash() {
FILE: actix/tests/test_arbiter.rs
type Ping (line 10) | struct Ping;
type Result (line 13) | type Result = ();
type MyActor (line 16) | struct MyActor(Arc<AtomicUsize>);
type Result (line 23) | type Result = ();
method handle (line 25) | fn handle(&mut self, _: Ping, _: &mut actix::Context<MyActor>) {
type Context (line 19) | type Context = Context<Self>;
function test_start_actor_message (line 33) | fn test_start_actor_message() {
FILE: actix/tests/test_atomic_response.rs
type Num (line 10) | struct Num(usize);
type MyActor (line 12) | struct MyActor(usize);
type Result (line 19) | type Result = AtomicResponse<Self, usize>;
method handle (line 21) | fn handle(&mut self, msg: Num, _: &mut Self::Context) -> Self::Result {
type Context (line 15) | type Context = Context<Self>;
function test_atomic_response (line 34) | async fn test_atomic_response() {
FILE: actix/tests/test_connected.rs
type MyActor (line 8) | struct MyActor;
type Context (line 11) | type Context = Context<Self>;
method started (line 13) | fn started(&mut self, ctx: &mut Self::Context) {
method stopped (line 21) | fn stopped(&mut self, _ctx: &mut Self::Context) {
function test_connected (line 27) | async fn test_connected() {
FILE: actix/tests/test_context.rs
type Op (line 20) | enum Op {
type StreamRx (line 28) | struct StreamRx {
type Item (line 33) | type Item = Ping;
method poll_next (line 35) | fn poll_next(self: Pin<&mut Self>, cx: &mut StdContext<'_>) -> Poll<Opti...
type MyActor (line 41) | struct MyActor {
type Result (line 89) | type Result = ();
method handle (line 91) | fn handle(&mut self, _: TimeoutMessage, _: &mut Self::Context) {
type Context (line 46) | type Context = actix::Context<Self>;
method started (line 48) | fn started(&mut self, ctx: &mut Context<MyActor>) {
method stopped (line 77) | fn stopped(&mut self, _: &mut Context<MyActor>) {
type TimeoutMessage (line 82) | struct TimeoutMessage;
type Result (line 85) | type Result = ();
function test_add_timeout (line 100) | fn test_add_timeout() {
function test_add_timeout_cancel (line 107) | fn test_add_timeout_cancel() {
function test_add_timeout_stop (line 120) | fn test_add_timeout_stop() {
function test_run_after (line 130) | fn test_run_after() {
function test_run_after_stop (line 137) | fn test_run_after_stop() {
type ContextWait (line 146) | struct ContextWait {
type Result (line 161) | type Result = ();
method handle (line 163) | fn handle(&mut self, _: Ping, ctx: &mut Self::Context) {
type Context (line 151) | type Context = actix::Context<Self>;
type Ping (line 154) | struct Ping;
type Result (line 157) | type Result = ();
function test_wait_context (line 175) | fn test_wait_context() {
function test_message_stream_wait_context (line 193) | fn test_message_stream_wait_context() {
function test_stream_wait_context (line 217) | fn test_stream_wait_context() {
type ContextNoWait (line 239) | struct ContextNoWait {
type Result (line 248) | type Result = ();
method handle (line 250) | fn handle(&mut self, _: Ping, _: &mut Self::Context) {
type Context (line 244) | type Context = actix::Context<Self>;
function test_nowait_context (line 257) | async fn test_nowait_context() {
function test_message_stream_nowait_context (line 274) | async fn test_message_stream_nowait_context() {
function test_stream_nowait_context (line 296) | fn test_stream_nowait_context() {
function test_notify (line 324) | fn test_notify() {
type ContextHandle (line 350) | struct ContextHandle {
method handle (line 358) | fn handle(&mut self, _: Ping, ctx: &mut Self::Context) {
type Context (line 354) | type Context = Context<Self>;
function test_current_context_handle (line 365) | fn test_current_context_handle() {
function test_start_from_context (line 389) | fn test_start_from_context() {
type CancelHandler (line 411) | struct CancelHandler {
method handle (line 426) | fn handle(&mut self, _: CancelPacket, ctx: &mut Context<Self>) {
type Context (line 416) | type Context = Context<Self>;
method stopped (line 418) | fn stopped(&mut self, _: &mut Context<Self>) {
type CancelPacket (line 423) | struct CancelPacket;
function test_cancel_handler (line 432) | fn test_cancel_handler() {
type CancelLater (line 460) | struct CancelLater {
type Result (line 480) | type Result = ();
method handle (line 482) | fn handle(&mut self, _: CancelMessage, ctx: &mut Self::Context) {
type Context (line 465) | type Context = Context<Self>;
method started (line 467) | fn started(&mut self, ctx: &mut Context<Self>) {
type CancelMessage (line 473) | struct CancelMessage;
type Result (line 476) | type Result = ();
function test_cancel_completed_with_no_context_item (line 488) | fn test_cancel_completed_with_no_context_item() {
type TestActor (line 513) | struct TestActor;
type Result (line 534) | type Result = ();
method handle (line 536) | fn handle(&mut self, msg: Msg, ctx: &mut Self::Context) -> Self::Result {
type Context (line 516) | type Context = Context<Self>;
method started (line 518) | fn started(&mut self, ctx: &mut Self::Context) {
type Msg (line 525) | struct Msg(Option<oneshot::Sender<()>>);
method drop (line 528) | fn drop(&mut self) {
function cancels (line 547) | fn cancels() {
type TestFuture (line 572) | struct TestFuture(Rc<AtomicBool>);
method new (line 575) | fn new(state: Rc<AtomicBool>) -> Self {
type Output (line 582) | type Output = ();
method poll (line 584) | fn poll(self: Pin<&mut Self>, _: &mut StdContext<'_>) -> Poll<Self::Outp...
method drop (line 590) | fn drop(&mut self) {
type TestCase (line 595) | enum TestCase {
type TestActor (line 600) | struct TestActor(TestCase);
type Result (line 534) | type Result = ();
method handle (line 536) | fn handle(&mut self, msg: Msg, ctx: &mut Self::Context) -> Self::Result {
type Context (line 603) | type Context = Context<Self>;
method started (line 605) | fn started(&mut self, ctx: &mut Self::Context) {
method restarting (line 619) | fn restarting(&mut self, ctx: &mut Self::Context) {
function cancels_spawned_futures (line 625) | fn cancels_spawned_futures() {
function clears_await_queue (line 643) | fn clears_await_queue() {
FILE: actix/tests/test_fut.rs
type MyActor (line 11) | struct MyActor {
type Context (line 16) | type Context = actix::Context<Self>;
method started (line 18) | fn started(&mut self, ctx: &mut Self::Context) {
function test_fut_timeout (line 36) | fn test_fut_timeout() {
type MyStreamActor (line 50) | struct MyStreamActor {
type Context (line 55) | type Context = actix::Context<Self>;
method started (line 57) | fn started(&mut self, ctx: &mut Self::Context) {
type MyStreamActor2 (line 85) | struct MyStreamActor2 {
type Result (line 100) | type Result = ResponseActFuture<Self, ()>;
method handle (line 102) | fn handle(&mut self, msg: TakeWhileMsg, _: &mut Context<Self>) -> Self...
type Result (line 130) | type Result = ResponseActFuture<Self, ()>;
method handle (line 132) | fn handle(&mut self, msg: SkipWhileMsg, _: &mut Context<Self>) -> Self...
type Result (line 163) | type Result = ResponseActFuture<Self, Vec<usize>>;
method handle (line 165) | fn handle(&mut self, msg: CollectMsg, _: &mut Context<Self>) -> Self::...
type Result (line 187) | type Result = ResponseActFuture<Self, Result<isize, u32>>;
method handle (line 189) | fn handle(&mut self, msg: TryFutureMsg, _: &mut Context<Self>) -> Self...
type Context (line 90) | type Context = actix::Context<Self>;
type TakeWhileMsg (line 93) | struct TakeWhileMsg(usize);
type Result (line 96) | type Result = ();
type SkipWhileMsg (line 123) | struct SkipWhileMsg(usize);
type Result (line 126) | type Result = ();
type CollectMsg (line 156) | struct CollectMsg(usize);
type Result (line 159) | type Result = Vec<usize>;
type TryFutureMsg (line 180) | struct TryFutureMsg(usize);
type Result (line 183) | type Result = Result<isize, u32>;
function test_stream_timeout (line 213) | fn test_stream_timeout() {
function test_stream_take_while (line 227) | fn test_stream_take_while() {
function test_stream_skip_while (line 235) | fn test_stream_skip_while() {
function test_stream_collect (line 243) | fn test_stream_collect() {
function test_try_future (line 253) | fn test_try_future() {
FILE: actix/tests/test_lifecycle.rs
type MyActor (line 15) | struct MyActor {
type Context (line 24) | type Context = actix::Context<Self>;
method started (line 26) | fn started(&mut self, _: &mut Self::Context) {
method stopping (line 30) | fn stopping(&mut self, ctx: &mut Self::Context) -> Running {
method stopped (line 48) | fn stopped(&mut self, _: &mut Self::Context) {
type MySyncActor (line 53) | struct MySyncActor {
type Context (line 61) | type Context = actix::SyncContext<Self>;
method started (line 63) | fn started(&mut self, _: &mut Self::Context) {
method stopping (line 66) | fn stopping(&mut self, _: &mut Self::Context) -> Running {
method stopped (line 76) | fn stopped(&mut self, _: &mut Self::Context) {
function test_active_address (line 82) | fn test_active_address() {
function test_stop_after_drop_address (line 117) | fn test_stop_after_drop_address() {
function test_stop_after_drop_sync_address (line 149) | fn test_stop_after_drop_sync_address() {
function test_stop_after_drop_sync_actor (line 180) | fn test_stop_after_drop_sync_actor() {
function test_stop (line 222) | fn test_stop() {
function test_stop_restore_after_stopping (line 252) | fn test_stop_restore_after_stopping() {
FILE: actix/tests/test_messages.rs
type SessionActor (line 7) | struct SessionActor {
method new (line 12) | fn new() -> Self {
method session_count (line 18) | fn session_count(&self) -> usize {
method sessions (line 22) | fn sessions(&self) -> Vec<usize> {
method add_session (line 26) | fn add_session(&mut self, id: usize) -> Result<usize, String> {
type Result (line 43) | type Result = Result<usize, String>;
method handle (line 45) | fn handle(&mut self, id: AddSession, _: &mut Context<Self>) -> Self::R...
type Result (line 55) | type Result = usize;
method handle (line 57) | fn handle(&mut self, _: GetSessionCount, _: &mut Context<Self>) -> Sel...
type Result (line 67) | type Result = Vec<usize>;
method handle (line 69) | fn handle(&mut self, _: GetConnectedSessions, _: &mut Context<Self>) -...
type Result (line 79) | type Result = Option<usize>;
method handle (line 81) | fn handle(&mut self, id: GetSessionById, _: &mut Context<Self>) -> Sel...
type Context (line 35) | type Context = Context<Self>;
type AddSession (line 40) | struct AddSession(usize);
type GetSessionCount (line 52) | struct GetSessionCount;
type GetConnectedSessions (line 64) | struct GetConnectedSessions;
type GetSessionById (line 76) | struct GetSessionById(usize);
function test_different_message_result_types (line 87) | async fn test_different_message_result_types() {
FILE: actix/tests/test_sink.rs
type ByteSender (line 13) | type ByteSender = mpsc::UnboundedSender<u8>;
type MySink (line 15) | struct MySink {
type Error (line 23) | type Error = ();
method poll_ready (line 25) | fn poll_ready(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Resu...
method start_send (line 49) | fn start_send(self: Pin<&mut Self>, bytes: Bytes) -> Result<(), Self::...
method poll_flush (line 54) | fn poll_flush(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Resu...
method poll_close (line 58) | fn poll_close(self: Pin<&mut Self>, cx: &mut Context) -> Poll<Result<(...
type SinkUnboundedSender (line 63) | struct SinkUnboundedSender {
type Error (line 68) | type Error = mpsc::error::SendError<Bytes>;
method poll_ready (line 70) | fn poll_ready(self: Pin<&mut Self>, _: &mut Context<'_>) -> Poll<Resul...
method start_send (line 74) | fn start_send(self: Pin<&mut Self>, t: Bytes) -> Result<(), Self::Erro...
method poll_flush (line 78) | fn poll_flush(self: Pin<&mut Self>, _: &mut Context<'_>) -> Poll<Resul...
method poll_close (line 82) | fn poll_close(self: Pin<&mut Self>, _: &mut Context) -> Poll<Result<()...
type Data (line 87) | struct Data {
type Result (line 93) | type Result = ();
type MyActor (line 96) | struct MyActor {
method finished (line 105) | fn finished(&mut self, _ctxt: &mut Self::Context) {
type Result (line 111) | type Result = ();
method handle (line 112) | fn handle(&mut self, data: Data, _ctxt: &mut Self::Context) {
type Context (line 101) | type Context = actix::Context<Self>;
function test_send_1 (line 121) | async fn test_send_1() {
function test_send_2 (line 152) | async fn test_send_2() {
function test_send_error (line 190) | async fn test_send_error() {
type AnotherActor (line 219) | struct AnotherActor {
method finished (line 228) | fn finished(&mut self, _ctxt: &mut Self::Context) {
type Result (line 234) | type Result = ();
method handle (line 235) | fn handle(&mut self, data: Data, _ctxt: &mut Self::Context) {
type Context (line 224) | type Context = actix::Context<Self>;
function test_send_bytes (line 245) | async fn test_send_bytes() {
function test_send_single_bytes (line 265) | async fn test_send_single_bytes() {
FILE: actix/tests/test_supervisor.rs
type Die (line 12) | struct Die;
type Result (line 15) | type Result = ();
type MyActor (line 18) | struct MyActor(Arc<AtomicUsize>, Arc<AtomicUsize>, Arc<AtomicUsize>);
method restarting (line 28) | fn restarting(&mut self, _: &mut actix::Context<MyActor>) {
type Result (line 34) | type Result = ();
method handle (line 36) | fn handle(&mut self, _: Die, ctx: &mut actix::Context<MyActor>) {
type Context (line 21) | type Context = Context<Self>;
method started (line 23) | fn started(&mut self, _: &mut Context<MyActor>) {
function test_supervisor_restart (line 43) | fn test_supervisor_restart() {
FILE: actix/tests/test_sync.rs
type Fibonacci (line 8) | struct Fibonacci(pub u32);
type Result (line 11) | type Result = Result<u64, ()>;
type SyncActor (line 14) | struct SyncActor {
type Result (line 34) | type Result = Result<u64, ()>;
method handle (line 36) | fn handle(&mut self, msg: Fibonacci, _: &mut Self::Context) -> Self::R...
type Context (line 22) | type Context = SyncContext<Self>;
method started (line 24) | fn started(&mut self, _: &mut Self::Context) {
function test_sync (line 64) | fn test_sync() {
Condensed preview — 109 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (448K chars).
[
{
"path": ".codecov.yml",
"chars": 271,
"preview": "comment: false\n\ncoverage:\n status:\n project:\n default:\n threshold: 100% # make CI green\n patch:\n "
},
{
"path": ".github/ISSUE_TEMPLATE/bug_report.md",
"chars": 1265,
"preview": "---\nname: bug report\nabout: create a bug report\n---\n\nYour issue may already be reported! Please search on the [Actix iss"
},
{
"path": ".github/ISSUE_TEMPLATE/config.yml",
"chars": 162,
"preview": "blank_issues_enabled: true\ncontact_links:\n - name: Actix Discord\n url: https://discord.gg/NWpN5mmg3x\n about: Acti"
},
{
"path": ".github/PULL_REQUEST_TEMPLATE.md",
"chars": 790,
"preview": "<!-- Thanks for considering contributing actix! -->\n<!-- Please fill out the following to make our reviews easy. -->\n\n##"
},
{
"path": ".github/dependabot.yml",
"chars": 297,
"preview": "version: 2\nupdates:\n - package-ecosystem: github-actions\n directory: /\n schedule:\n interval: monthly\n - pac"
},
{
"path": ".github/workflows/ci-post-merge.yml",
"chars": 1202,
"preview": "name: CI (post-merge)\n\non:\n push:\n branches: [main]\n\npermissions:\n contents: read\n\nconcurrency:\n group: ${{ github"
},
{
"path": ".github/workflows/ci.yml",
"chars": 2102,
"preview": "name: CI\n\non:\n pull_request:\n types: [opened, synchronize, reopened]\n merge_group:\n types: [checks_requested]\n "
},
{
"path": ".github/workflows/clippy-fmt.yml",
"chars": 1013,
"preview": "name: Lint\n\non:\n pull_request:\n types: [opened, synchronize, reopened]\n\npermissions:\n contents: read\n\nconcurrency:\n"
},
{
"path": ".github/workflows/coverage.yml",
"chars": 845,
"preview": "name: Coverage\n\non:\n push:\n branches: [main]\n\npermissions:\n contents: read\n\nconcurrency:\n group: ${{ github.workfl"
},
{
"path": ".gitignore",
"chars": 110,
"preview": "/gh-pages\n__pycache__\n\n*.so\n*.out\n*.pyc\n*.pid\n*.sock\n*~\ntarget/\nactix/examples/chat/target/\n.idea\n\n/lcov.info\n"
},
{
"path": ".prettierrc.yml",
"chars": 197,
"preview": "overrides:\n - files: '*.md'\n options:\n printWidth: 9999\n proseWrap: never\n - files: '*.{yml,yaml}'\n op"
},
{
"path": ".rustfmt.toml",
"chars": 97,
"preview": "group_imports = \"StdExternalCrate\"\nimports_granularity = \"Crate\"\nuse_field_init_shorthand = true\n"
},
{
"path": ".vscode/settings.json",
"chars": 312,
"preview": "{\n \"cSpell.words\": [\n \"actix\",\n \"bitflags\",\n \"clippy\",\n \"codecov\",\n \"doctest\",\n "
},
{
"path": "CODE_OF_CONDUCT.md",
"chars": 3351,
"preview": "# Contributor Covenant Code of Conduct\n\n## Our Pledge\n\nIn the interest of fostering an open and welcoming environment, w"
},
{
"path": "Cargo.toml",
"chars": 420,
"preview": "[workspace]\nresolver = \"2\"\nmembers = [\n \"actix\",\n \"actix-broker\",\n \"actix-derive\",\n]\n\n[workspace.package]\nlicen"
},
{
"path": "LICENSE-APACHE",
"chars": 11344,
"preview": " Apache License\n Version 2.0, January 2004\n "
},
{
"path": "LICENSE-MIT",
"chars": 1054,
"preview": "Copyright (c) 2017 Actix Team\n\nPermission is hereby granted, free of charge, to any\nperson obtaining a copy of this soft"
},
{
"path": "actix/CHANGES.md",
"chars": 17071,
"preview": "# CHANGES\n\n## Unreleased\n\n- Minimum supported Rust version (MSRV) is now 1.76.\n\n## 0.13.5\n\n- Add `Registry::try_get()` m"
},
{
"path": "actix/Cargo.toml",
"chars": 1797,
"preview": "[package]\nname = \"actix\"\nversion = \"0.13.5\"\nauthors = [\n \"Nikolay Kim <fafhrd91@gmail.com>\",\n]\ndescription = \"Actor f"
},
{
"path": "actix/MIGRATION.md",
"chars": 1431,
"preview": "## 0.10.0\n\n- `SinkWrite::write` no longer return a Result, instead it returns an `Option<I>` containing the item that ha"
},
{
"path": "actix/README.md",
"chars": 7672,
"preview": "<div align=\"center\">\n <h1>Actix</h1>\n <p>\n <strong>Actor framework for Rust</strong>\n </p>\n <p>\n\n<!-- prettier-ig"
},
{
"path": "actix/examples/README.md",
"chars": 896,
"preview": "# Actix Examples\n\nThe following examples complement the documentation and can help you understand how to use Actix:\n\n1. "
},
{
"path": "actix/examples/fibonacci.rs",
"chars": 1320,
"preview": "//! Example of sync actor. It can be used for cpu bound tasks. Only one sync\n//! actor runs within arbiter's thread. Syn"
},
{
"path": "actix/examples/mock.rs",
"chars": 1814,
"preview": "//! Mock example\n//!\n//! Mocking an actor and setting it on the `SystemRegistry`. This can be\n//! done so you can test a"
},
{
"path": "actix/examples/ping.rs",
"chars": 828,
"preview": "use actix::prelude::*;\n\n/// Define `Ping` message\nstruct Ping(usize);\n\nimpl Message for Ping {\n type Result = usize;\n"
},
{
"path": "actix/examples/ring.rs",
"chars": 3732,
"preview": "//! Ring benchmark inspired by Programming Erlang: Software for a\n//! Concurrent World, by Joe Armstrong, Chapter 8.11.2"
},
{
"path": "actix/examples/weak_addr.rs",
"chars": 3364,
"preview": "//! WeakAddr example\n//!\n//! With a weak address you can register an client actor's addrs with a\n//! service and still g"
},
{
"path": "actix/examples/weak_recipient.rs",
"chars": 4618,
"preview": "//! WeakRecipient example\n//!\n//! With a weak recipient you can register any client actor's addrs with a\n//! service and"
},
{
"path": "actix/src/actor.rs",
"chars": 15193,
"preview": "use std::time::Duration;\n\nuse actix_rt::ArbiterHandle;\nuse futures_core::stream::Stream;\nuse log::error;\n\nuse crate::{\n "
},
{
"path": "actix/src/actors/mocker.rs",
"chars": 2743,
"preview": "//! Mocking utility actor.\n//!\n//! This actor wraps any actor, and replaces instances of that actor with\n//! mocker acto"
},
{
"path": "actix/src/actors/mod.rs",
"chars": 35,
"preview": "//! Helper actors\n\npub mod mocker;\n"
},
{
"path": "actix/src/address/channel.rs",
"chars": 29518,
"preview": "//! This is copy of [sync/mpsc/](https://github.com/rust-lang/futures-rs)\n\nuse std::{\n fmt,\n hash::{Hash, Hasher},"
},
{
"path": "actix/src/address/envelope.rs",
"chars": 2171,
"preview": "use tokio::sync::oneshot::Sender;\n\nuse crate::{\n actor::{Actor, AsyncContext},\n context::Context,\n handler::{Ha"
},
{
"path": "actix/src/address/message.rs",
"chars": 2595,
"preview": "use std::{\n future::Future,\n pin::Pin,\n task::{self, Poll},\n time::Duration,\n};\n\nuse pin_project_lite::pin_p"
},
{
"path": "actix/src/address/mod.rs",
"chars": 12972,
"preview": "use std::{\n error, fmt,\n hash::{Hash, Hasher},\n};\n\npub(crate) mod channel;\nmod envelope;\nmod message;\nmod queue;\n\n"
},
{
"path": "actix/src/address/queue.rs",
"chars": 6803,
"preview": "/* Copyright (c) 2010-2011 Dmitry Vyukov. All rights reserved.\n * Redistribution and use in source and binary forms, wit"
},
{
"path": "actix/src/clock.rs",
"chars": 296,
"preview": "//! Utilities for tracking time.\n//!\n//! This module provides a number of types for executing code after a set period of"
},
{
"path": "actix/src/context.rs",
"chars": 5792,
"preview": "use std::fmt;\n\nuse crate::{\n actor::{Actor, ActorContext, ActorState, AsyncContext, SpawnHandle},\n address::{Addr,"
},
{
"path": "actix/src/context_impl.rs",
"chars": 15346,
"preview": "use std::{\n fmt,\n future::Future,\n pin::Pin,\n task::{Context, Poll},\n};\n\nuse bitflags::bitflags;\nuse futures"
},
{
"path": "actix/src/context_items.rs",
"chars": 3683,
"preview": "use std::{\n future::Future,\n pin::Pin,\n task::{self, Poll},\n time::Duration,\n};\n\nuse futures_core::{ready, s"
},
{
"path": "actix/src/fut/future/either.rs",
"chars": 1087,
"preview": "use std::{\n pin::Pin,\n task::{Context, Poll},\n};\n\nuse futures_util::future::Either;\n\nuse crate::{actor::Actor, fut"
},
{
"path": "actix/src/fut/future/map.rs",
"chars": 1570,
"preview": "use std::{\n pin::Pin,\n task::{Context, Poll},\n};\n\nuse futures_core::ready;\nuse pin_project_lite::pin_project;\n\nuse"
},
{
"path": "actix/src/fut/future/mod.rs",
"chars": 7607,
"preview": "use std::{\n future::Future,\n marker::PhantomData,\n ops::{Deref, DerefMut},\n pin::Pin,\n task::{Context, Po"
},
{
"path": "actix/src/fut/future/result.rs",
"chars": 2326,
"preview": "//! Definition of the [`Ready`] (immediately finished) combinator\n\nuse std::{\n future::Future,\n pin::Pin,\n task"
},
{
"path": "actix/src/fut/future/then.rs",
"chars": 1953,
"preview": "use std::{\n pin::Pin,\n task::{self, Poll},\n};\n\nuse futures_core::ready;\nuse pin_project_lite::pin_project;\n\nuse cr"
},
{
"path": "actix/src/fut/future/timeout.rs",
"chars": 1359,
"preview": "use std::{\n future::Future,\n pin::Pin,\n task::{Context, Poll},\n time::Duration,\n};\n\nuse pin_project_lite::pi"
},
{
"path": "actix/src/fut/mod.rs",
"chars": 417,
"preview": "//! Custom `Future` and `Stream` implementation with `actix` support.\n\npub mod future;\npub mod stream;\npub mod try_futur"
},
{
"path": "actix/src/fut/stream/collect.rs",
"chars": 1284,
"preview": "use std::{\n mem,\n pin::Pin,\n task::{Context, Poll},\n};\n\nuse futures_core::ready;\nuse pin_project_lite::pin_proj"
},
{
"path": "actix/src/fut/stream/finish.rs",
"chars": 947,
"preview": "use std::{\n pin::Pin,\n task::{Context, Poll},\n};\n\nuse futures_core::ready;\nuse pin_project_lite::pin_project;\n\nuse"
},
{
"path": "actix/src/fut/stream/fold.rs",
"chars": 2094,
"preview": "use std::{\n pin::Pin,\n task::{Context, Poll},\n};\n\nuse futures_core::ready;\nuse pin_project_lite::pin_project;\n\nuse"
},
{
"path": "actix/src/fut/stream/map.rs",
"chars": 1094,
"preview": "use std::{\n pin::Pin,\n task::{Context, Poll},\n};\n\nuse futures_core::ready;\nuse pin_project_lite::pin_project;\n\nuse"
},
{
"path": "actix/src/fut/stream/mod.rs",
"chars": 6623,
"preview": "use std::{\n marker::PhantomData,\n pin::Pin,\n task::{Context, Poll},\n time::Duration,\n};\n\npub use collect::Co"
},
{
"path": "actix/src/fut/stream/skip_while.rs",
"chars": 2161,
"preview": "use std::{\n pin::Pin,\n task::{self, Poll},\n};\n\nuse futures_core::ready;\nuse pin_project_lite::pin_project;\n\nuse cr"
},
{
"path": "actix/src/fut/stream/take_while.rs",
"chars": 2182,
"preview": "use std::{\n pin::Pin,\n task::{self, Poll},\n};\n\nuse futures_core::ready;\nuse pin_project_lite::pin_project;\n\nuse cr"
},
{
"path": "actix/src/fut/stream/then.rs",
"chars": 1630,
"preview": "use std::{\n pin::Pin,\n task::{Context, Poll},\n};\n\nuse futures_core::ready;\nuse pin_project_lite::pin_project;\n\nuse"
},
{
"path": "actix/src/fut/stream/timeout.rs",
"chars": 1815,
"preview": "use std::{\n future::Future,\n pin::Pin,\n task::{Context, Poll},\n time::Duration,\n};\n\nuse pin_project_lite::pi"
},
{
"path": "actix/src/fut/try_future/and_then.rs",
"chars": 2059,
"preview": "use std::{\n pin::Pin,\n task::{Context, Poll},\n};\n\nuse futures_util::ready;\nuse pin_project_lite::pin_project;\n\nuse"
},
{
"path": "actix/src/fut/try_future/map_err.rs",
"chars": 1723,
"preview": "use std::{\n pin::Pin,\n task::{Context, Poll},\n};\n\nuse futures_core::ready;\nuse pin_project_lite::pin_project;\n\nuse"
},
{
"path": "actix/src/fut/try_future/map_ok.rs",
"chars": 1711,
"preview": "use std::{\n pin::Pin,\n task::{Context, Poll},\n};\n\nuse futures_core::ready;\nuse pin_project_lite::pin_project;\n\nuse"
},
{
"path": "actix/src/fut/try_future/mod.rs",
"chars": 4476,
"preview": "use std::{\n pin::Pin,\n task::{Context, Poll},\n};\n\nuse crate::{actor::Actor, fut::future::ActorFuture};\n\nmod and_th"
},
{
"path": "actix/src/handler.rs",
"chars": 15824,
"preview": "use std::{fmt, future::Future, pin::Pin, sync::Arc};\n\npub use tokio::sync::oneshot::Sender as OneshotSender;\n\nuse crate:"
},
{
"path": "actix/src/io.rs",
"chars": 17134,
"preview": "use std::{\n cell::RefCell,\n collections::VecDeque,\n io,\n marker::PhantomData,\n ops::DerefMut,\n pin::Pi"
},
{
"path": "actix/src/lib.rs",
"chars": 5507,
"preview": "//! Actix is an actor framework.\n//!\n//! [Actors](Actor) are objects which encapsulate state and behavior, they communic"
},
{
"path": "actix/src/mailbox.rs",
"chars": 2347,
"preview": "use std::{fmt, pin::Pin, task, task::Poll};\n\nuse futures_core::stream::Stream;\n\nuse crate::{\n actor::{Actor, AsyncCon"
},
{
"path": "actix/src/registry.rs",
"chars": 9702,
"preview": "//! Actors registry\n//!\n//! An Actor can register itself as a service. A Service can be defined as an\n//! `ArbiterServic"
},
{
"path": "actix/src/stream.rs",
"chars": 3842,
"preview": "use std::{\n pin::Pin,\n task::{Context, Poll},\n};\n\nuse futures_core::{ready, stream::Stream};\nuse log::error;\nuse p"
},
{
"path": "actix/src/supervisor.rs",
"chars": 4737,
"preview": "use std::{\n future::Future,\n pin::Pin,\n task::{self, Poll},\n};\n\nuse actix_rt::ArbiterHandle;\nuse pin_project_li"
},
{
"path": "actix/src/sync.rs",
"chars": 12192,
"preview": "//! Sync Actors support\n//!\n//! Sync Actors are actors that run multiple instances on a thread pool.\n//! This is useful "
},
{
"path": "actix/src/utils.rs",
"chars": 6013,
"preview": "use std::{\n future::Future,\n pin::Pin,\n task::{Context, Poll},\n time::Duration,\n};\n\nuse futures_core::ready;"
},
{
"path": "actix/tests/derive.rs",
"chars": 4091,
"preview": "#![cfg(feature = \"macros\")]\n\nuse std::ops::Mul;\n\nuse actix::prelude::*;\n\n#[derive(Message)]\n#[rtype(result = \"()\")]\nstru"
},
{
"path": "actix/tests/test_actor.rs",
"chars": 8574,
"preview": "#![cfg(feature = \"macros\")]\n\nuse std::{\n sync::{\n atomic::{AtomicBool, AtomicUsize, Ordering},\n mpsc, A"
},
{
"path": "actix/tests/test_address.rs",
"chars": 15004,
"preview": "use std::{\n collections::HashSet,\n sync::{\n atomic::{AtomicUsize, Ordering},\n Arc,\n },\n time::"
},
{
"path": "actix/tests/test_arbiter.rs",
"chars": 1361,
"preview": "use std::sync::{\n atomic::{AtomicUsize, Ordering},\n Arc,\n};\n\nuse actix::prelude::*;\nuse tokio::sync::oneshot;\n\n#[d"
},
{
"path": "actix/tests/test_atomic_response.rs",
"chars": 1309,
"preview": "#![cfg(feature = \"macros\")]\n\nuse std::time::{Duration, Instant};\n\nuse actix::{clock::sleep, prelude::*};\nuse futures_uti"
},
{
"path": "actix/tests/test_connected.rs",
"chars": 694,
"preview": "#![cfg(feature = \"macros\")]\n\nuse std::time::Duration;\n\nuse actix::prelude::*;\nuse actix_rt::time::sleep;\n\nstruct MyActor"
},
{
"path": "actix/tests/test_context.rs",
"chars": 16369,
"preview": "#![cfg(feature = \"macros\")]\n#![allow(clippy::let_unit_value)]\n\nuse std::{\n pin::Pin,\n sync::{\n atomic::{Ato"
},
{
"path": "actix/tests/test_fut.rs",
"chars": 6743,
"preview": "use std::{\n sync::{\n atomic::{AtomicBool, Ordering},\n Arc,\n },\n time::Duration,\n};\n\nuse actix::{c"
},
{
"path": "actix/tests/test_lifecycle.rs",
"chars": 8141,
"preview": "#![allow(clippy::let_unit_value)]\n\nuse std::{\n sync::{\n atomic::{AtomicBool, Ordering},\n Arc, Mutex,\n "
},
{
"path": "actix/tests/test_messages.rs",
"chars": 3238,
"preview": "#![cfg(feature = \"macros\")]\n\nuse std::collections::HashSet;\n\nuse actix::prelude::*;\n\nstruct SessionActor {\n sessions:"
},
{
"path": "actix/tests/test_sink.rs",
"chars": 7006,
"preview": "#![cfg(feature = \"macros\")]\n\nuse std::{\n pin::Pin,\n task::{Context, Poll},\n};\n\nuse actix::{io::SinkWrite, prelude:"
},
{
"path": "actix/tests/test_supervisor.rs",
"chars": 1809,
"preview": "use std::{\n sync::{\n atomic::{AtomicUsize, Ordering},\n Arc, Mutex,\n },\n time::Duration,\n};\n\nuse a"
},
{
"path": "actix/tests/test_sync.rs",
"chars": 2496,
"preview": "use std::sync::{\n atomic::{AtomicUsize, Ordering},\n Arc, Condvar, Mutex,\n};\n\nuse actix::prelude::*;\n\nstruct Fibona"
},
{
"path": "actix-broker/CHANGES.md",
"chars": 698,
"preview": "# Changes\n\n## Unreleased\n\n- Minimum supported Rust version (MSRV) is now 1.76.\n\n## 0.4.4\n\n- Improve broker message perfo"
},
{
"path": "actix-broker/Cargo.toml",
"chars": 662,
"preview": "[package]\nname = \"actix-broker\"\nversion = \"0.4.4\"\nauthors = [\"Chris Ricketts <chris.ricketts@steribar.com>\"]\ndescription"
},
{
"path": "actix-broker/LICENSE-APACHE",
"chars": 11379,
"preview": " Apache License\n Version 2.0, January 2004\n "
},
{
"path": "actix-broker/LICENSE-MIT",
"chars": 1107,
"preview": "MIT License\n\nCopyright (c) 2018 Christopher Ricketts\nCopyright (c) 2021 Actix Team\n\nPermission is hereby granted, free o"
},
{
"path": "actix-broker/README.md",
"chars": 1102,
"preview": "# actix-broker\n\n> A message broker for the Actix actor framework. \n> Subscribe to and issue Messages easily in an async"
},
{
"path": "actix-broker/benches/broker.rs",
"chars": 6175,
"preview": "use std::{\n future::Future,\n sync::{\n atomic::{AtomicBool, AtomicU16, Ordering},\n mpsc::SyncSender,\n"
},
{
"path": "actix-broker/examples/actix-web.rs",
"chars": 1011,
"preview": "use std::io;\n\nuse actix::prelude::*;\nuse actix_broker::{Broker, BrokerSubscribe, SystemBroker};\nuse actix_web::{get, App"
},
{
"path": "actix-broker/examples/basic.rs",
"chars": 2185,
"preview": "use std::time::Duration;\n\nuse actix::prelude::*;\nuse actix_broker::{BrokerIssue, BrokerSubscribe, SystemBroker};\n\nstruct"
},
{
"path": "actix-broker/src/broker.rs",
"chars": 6858,
"preview": "use std::{\n any::{Any, TypeId},\n collections::HashMap,\n hash::BuildHasherDefault,\n marker::PhantomData,\n};\n\n"
},
{
"path": "actix-broker/src/issue.rs",
"chars": 2455,
"preview": "use std::any::TypeId;\n\nuse actix::prelude::*;\n\nuse crate::{\n broker::{ArbiterBroker, RegisteredBroker, SystemBroker},"
},
{
"path": "actix-broker/src/lib.rs",
"chars": 2945,
"preview": "//! A message broker for the Actix actor framework.\n//!\n//! The `actix_broker` crate contains `SystemService` and `Arbit"
},
{
"path": "actix-broker/src/msgs.rs",
"chars": 667,
"preview": "use std::any::TypeId;\n\nuse actix::prelude::*;\n\npub trait BrokerMsg: Message<Result = ()> + Send + Clone + 'static {}\n\nim"
},
{
"path": "actix-broker/src/subscribe.rs",
"chars": 3272,
"preview": "//! messages.\nuse std::any::TypeId;\n\nuse actix::{dev::ToEnvelope, prelude::*};\n\nuse crate::{\n broker::{ArbiterBroker,"
},
{
"path": "actix-broker/tests/delivery.rs",
"chars": 1507,
"preview": "extern crate actix;\nextern crate actix_broker;\n\nuse std::time::Duration;\n\nuse actix::{clock::sleep, prelude::*};\nuse act"
},
{
"path": "actix-broker/tests/general.rs",
"chars": 1457,
"preview": "extern crate actix;\nextern crate actix_broker;\n\nuse std::time::Duration;\n\nuse actix::prelude::*;\nuse actix_broker::{Brok"
},
{
"path": "actix-derive/CHANGES.md",
"chars": 909,
"preview": "# Changes\n\n## Unreleased\n\n- Minimum supported Rust version (MSRV) is now 1.76.\n\n## 0.6.2\n\n- Fix compile failures when us"
},
{
"path": "actix-derive/Cargo.toml",
"chars": 625,
"preview": "[package]\nname = \"actix_derive\"\nversion = \"0.6.2\"\nauthors = [\n \"Callym <hi@callym.com>\",\n \"Nikolay Kim <fafhrd91@g"
},
{
"path": "actix-derive/README.md",
"chars": 1602,
"preview": "# actix-derive\n\n> Derive macros for `actix` actors.\n\n<!-- prettier-ignore-start -->\n\n[]\n#![doc(html_logo_url = \"https://actix.rs/img/logo.png"
},
{
"path": "actix-derive/src/message.rs",
"chars": 5178,
"preview": "use proc_macro2::{Span, TokenStream};\nuse quote::{quote, ToTokens};\nuse syn::parse::Parser as _;\n\ntype AttributeArgs = s"
},
{
"path": "actix-derive/src/message_response.rs",
"chars": 845,
"preview": "use proc_macro2::TokenStream;\nuse quote::quote;\nuse syn::parse_quote;\n\npub fn expand(ast: &syn::DeriveInput) -> TokenStr"
},
{
"path": "actix-derive/tests/test_macro.rs",
"chars": 1146,
"preview": "use actix::{Actor, Context, Handler, System};\nuse actix_derive::{Message, MessageResponse};\n\n#[derive(MessageResponse)]\n"
},
{
"path": "actix-derive/tests/trybuild/message-response.rs",
"chars": 91,
"preview": "use actix::MessageResponse;\n\n#[derive(MessageResponse)]\nstruct Added(usize);\n\nfn main() {}\n"
},
{
"path": "actix-derive/tests/trybuild/message.rs",
"chars": 1010,
"preview": "use actix::prelude::*;\n\n#[derive(MessageResponse)]\nstruct Added(usize);\n\n#[derive(Message)]\n#[rtype(result = \"Added\")]\ns"
},
{
"path": "actix-derive/tests/trybuild/rt-main.rs",
"chars": 58,
"preview": "#[actix::main]\nasync fn main() {\n async { 1 }.await;\n}\n"
},
{
"path": "actix-derive/tests/trybuild.rs",
"chars": 319,
"preview": "/// Proc macro compile tests.\n///\n/// Only run on MSRV to ensure stable compile errors.\n#[rustversion_msrv::msrv]\n#[test"
},
{
"path": "justfile",
"chars": 2231,
"preview": "toolchain := \"\"\n\nmsrv := ```\n cargo metadata --format-version=1 \\\n | jq -r 'first(.packages[] | select(.source == "
}
]
About this extraction
This page contains the full source code of the actix/actix GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 109 files (415.9 KB), approximately 108.4k tokens, and a symbol index with 1073 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.