https://github.com/qqwy/rust-backdrop_arc
An Arc (atomically reference counted smart pointer) that supports customized dropping strategies using Backdrop.
https://github.com/qqwy/rust-backdrop_arc
memory-management no-std-alloc reference-counting rust rust-lang smart-pointer threading tokio-rs
Last synced: 2 months ago
JSON representation
An Arc (atomically reference counted smart pointer) that supports customized dropping strategies using Backdrop.
- Host: GitHub
- URL: https://github.com/qqwy/rust-backdrop_arc
- Owner: Qqwy
- License: apache-2.0
- Created: 2023-02-27T19:41:25.000Z (over 2 years ago)
- Default Branch: main
- Last Pushed: 2023-08-16T17:29:34.000Z (almost 2 years ago)
- Last Synced: 2025-03-18T17:46:26.834Z (3 months ago)
- Topics: memory-management, no-std-alloc, reference-counting, rust, rust-lang, smart-pointer, threading, tokio-rs
- Language: Rust
- Homepage: https://crates.io/crates/backdrop_arc
- Size: 198 KB
- Stars: 5
- Watchers: 2
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- License: LICENSE-APACHE
Awesome Lists containing this project
README
# BackdropArc [![Latest Version]][crates.io] [![License]][license path] [![requires: rustc 1.56+]][Rust 1.56.1]
[Latest Version]: https://img.shields.io/crates/v/backdrop_arc.svg
[crates.io]: https://crates.io/crates/backdrop_arc
[License]: https://img.shields.io/badge/license-MIT-blue.svg
[license path]: https://github.com/qqwy/rust-backdrop_arc/blob/main/LICENSE
[requires: rustc 1.56+]: https://img.shields.io/badge/rustc-1.56+-lightgray.svg
[Rust 1.56.1]: https://rust-lang.org/An Arc (atomically reference counted smart pointer) that supports customized dropping strategies using [backdrop](https://crates.io/crates/backdrop).
`backdrop_arc::Arc` works very much like a `std::sync::Arc`, except for two differences:
### 1. Drop strategies
When the last clone of a particular Arc goes out of scope, rather than dropping normally, the particular [BackdropStrategy](https://docs.rs/backdrop/latest/backdrop/trait.BackdropStrategy.html) is invoked. This way, dropping large or complex structures can be done in a background thread, background tokio task, delayed until later, etc.
This allows better reasoning about how long code using an Arc will take, since this is no longer dependent on 'do I own the last Arc or not?'.
An `backdrop_arc::Arc` behaves much like a [`Arc, S>>`](https://docs.rs/backdrop/latest/backdrop/struct.Backdrop.html#the-problem-with-arc),
in that the backdrop strategy is executed _when the last Arc clone goes out of scope_.
The difference with `Arc, S>>` is that there is no double pointer-indirection (arc -> box -> T), managing the allocated `T` is done directly in the Arc.[`backdrop_arc::Arc`]:
### 2. No weak pointers => smaller arcs, predictable drop behaviour
[`std::sync::Arc`] allows the usage of weak pointers. This is very helpful internally in self-referential structures (trees, graphs) but frequently not needed.
On the other hand, weak pointers are not 'free':
- They make every Arc instance bigger (3 words instead of 2), since instead of storing `(ptr, reference_count)` they need to store `(ptr, reference_count, weak_reference_count)`.
- They make dropping an `Arc` more complex. The 'drop glue' of `T` will run once the last strong reference goes out of scope. But to not make Weak pointers dangle, the _deallocation_ of `T` only happens when the last `Weak` pointer goes out of scope ([see here](https://doc.rust-lang.org/std/sync/struct.Arc.html#breaking-cycles-with-weak)). As you can imagine, this 'two part drop' interacts badly with `BackdropStrategy` where we want to e.g. move objects to a background thread on drop, because we need to make sure that the allocation of `T` lives long enough.Therefore, `backdrop_arc` is modeled on the excellent [`triomphe`](https://crates.io/crates/triomphe) library.
Converting a [`backdrop_arc::Arc`] to and from a [`triomphe::Arc`] is a zero-cost operation, as the two types are guaranteed to have the same representation in memory.
(The same holds true for [`backdrop_arc::UniqueArc`] <-> [`triomphe::UniqueArc`])Not supporting weak pointers enables a bunch of other features:
- [`backdrop_arc::Arc`] does not need any read-modify-update operations to handle the possibility of weak references.
- [`backdrop_arc::UniqueArc`] allows one to construct a temporarily-mutable Arc which can be converted to a regular [`backdrop_arc::Arc`] later.
- [`backdrop_arc::OffsetArc`] can be used transparently from C++ code and is compatible with (and can be converted to/from) [`backdrop_arc::Arc`].
- [`backdrop_arc::ArcBorrow`] is functionally similar to `&backdrop_arc::Arc`, however in memory it's simply `&T`. This makes it more flexible for FFI; the source of the borrow need not be an Arc pinned on the stack (and can instead be a pointer from C++, or an `OffsetArc`). Additionally, this helps avoid pointer-chasing.
- [`backdrop_arc::Arc`] has can be constructed for dynamically-sized types via `from_header_and_iter`
- [`backdrop_arc::ArcUnion`] is union of two [`backdrop_arc:Arc`]s which fits inside one word of memory[`std::sync::Arc`]:
[`backdrop_arc::Arc`]:
[`backdrop_arc::UniqueArc`]:
[`backdrop_arc::ArcBorrow`]:
[`backdrop_arc::ArcUnion`]:
[`backdrop_arc::OffsetArc`]:
[`triomphe::Arc`]:
[`triomphe::UniqueArc`]:# Features
- `backdrop_arc` supports no_std environments, as long as `alloc` is available, by disabling the (enabled by default) `std` feature.
- `serde`: Enables serialization/deserialization with the [`serde`](https://crates.io/crates/serde) crate.
- `stable_deref_trait`: Implements the `StableDeref` trait from the [`stable_deref_trait`](https://crates.io/crates/stable_deref_trait) crate for [`backdrop_arc::Arc`].
- `arc-swap`: Use [`backdrop_arc::Arc`] together with the [`arc-swap`](https://crates.io/crates/arc-swap) crate.
- `triomphe`: Convert (zero-cost) between [`triomphe::Arc`] <-> [`backdrop_arc::Arc`] (and [`backdrop_arc::UniqueArc`] <-> [`triomphe::UniqueArc`]).
- `unsize` use [`backdrop_arc::Arc`] together with the [`unsize`](https://crates.io/crates/unsize) crate.
- `yoke`: Implements the [`CloneableCart`](https://docs.rs/yoke/0.6.2/yoke/trait.CloneableCart.html) trait from the the [`yoke`](https://crates.io/crates/yoke) crate for [`backdrop_arc::Arc`], making it easier to use in zero-copy serialization scenarios.[`triomphe::Arc`]:
[`triomphe::UniqueArc`]:## Attribution
The source code of `backdrop_arc` is very heavily based on (and originally a fork of) [`triomphe`](https://crates.io/crates/triomphe),
which itself originates from [`servo_arc`](https://crates.io/crates/servo_arc).## MSRV
The Minimum Supported Rust Version of backdrop_arc is Rust 1.56.1, because `backdrop` uses the edition 2021 Rust syntax.
There are no (required) Rust features or (required) dependencies besides `backdrop`, making this a very lightweight and portable crate.## Changelog
- 0.3.0:
- Replace `Arc::clone_many` with a much more friendly implementation + signature, returning a new iterator type.
- 0.2.0:
- Adds optional support for `yoke` (to use a `backdrop_arc::Arc` as a [`yoke::CloneableCart`](https://docs.rs/yoke/0.6.2/yoke/trait.CloneableCart.html)). Enable with the `yoke` feature.
- Adds `Arc::clone_many` and `Arc::clone_many_into_slice`, allowing you to clone an Arc many times at once with only a single atomic barrier.
- 0.1.x: Initial version