10 stable releases
2.0.0 | Feb 24, 2025 |
---|---|
1.4.1 | Feb 9, 2024 |
1.3.0 | Mar 13, 2023 |
1.2.1 | Nov 5, 2022 |
1.0.0 | Nov 5, 2020 |
#128 in Concurrency
803 downloads per month
Used in supergit
17KB
275 lines
AtomPtr
A safe wrapper around std::sync::atomic::AtomPtr
, improving its
ergonomics, enforcing safety and indirection checks, and bringing some
extra tricks for more granular concurrent datastructure design.
Quickstart
use atomptr::AtomPtr;
// Create some complex data and create an AtomPtr around it
let my_data = String::from("std::sync::atomic::AtomicPtr");
let p = AtomPtr::new(my_data);
// A 'Ref' is a snapshot of the inner 'AtomPtr' value. Even if the
// unner value were to change, a Ref keeps an old snapshot alive until
// the last instance of it is dropped.
let p_ref = p.get_ref();
// 'AtomPtr' is copy-on-write, so we perform 'uwu_clone' (or 'uwu_copy') to
// get full ownership of the data referenced by the snapshot. We can then
// freely make changes to the data.
let my_data2 = p_ref
.uwu_clone()
.split("::")
.filter_map(|segmnt| match segmnt {
"std" => Some("atomptr"),
"sync" => Some("AtomPtr"),
_ => None,
})
.collect::<Vec<_>>()
.join("::");
// Use either `swap()` or `compare_exchange()` to replace the data
let _ = p.compare_exchange(p_ref, my_data2.clone()).unwrap_ref();
let p_ref = p.get_ref();
assert_eq!(p_ref.count(), 2);
assert_eq!(p_ref.uwu_clone(), my_data2);
Migrating from 1.x versions
Due to a few API changes the version was suddenly from 1.4.x
to 2.0.0
, not
giving any deprecation time for the newly removed items. To allow a
smoother upgrade path for existing consumers when upgrading can enable
the stable
feature, which will opt-out of the code-breaking changes
of the API, giving them time to port over their usage.
Furthermore deprecations have been made with this bump. Warnings turn
to errors in version 2.1.0
, and the stable
feature is removed in
version 2.2.0
This crate wraps a given T
into an Arc<T>
, then stores an "owned
reference" into the AtomicPtr
.
A safe wrapper around atomic pointers to build datastructures and
lock-free algorithms on top of. Only uses std
as a dependency.
The standard library contains an AtomicPtr
type, which by itself is
very unergonomic to use, because it deals with raw pointers. It is
very easy to misuse this API and get memory leaks or double-free.
This library makes some assumptions about how you would like to use
your data. Furthermore, it is dangerous to use raw pointers without
some other memory management strategy. This crate uses Arc<T>
to
handle reference lifetime management. Data in an AtomPtr<T>
is also
always heap allocated.
Following is a simple example.
use atomptr::AtomPtr;
struct MyData { name: String }
let data = MyData { name: "Kookie".into() };
let a = AtomPtr::new(data);
println!("Name is: {}", a.get_ref().name);
let old_ref = a.swap(MyData { name: "Bob".into() });
println!("Name now is: {}, was {}", a.get_ref().name, old_ref.name);
Because all data is wrapped by Arc<T>
internally, returning a
reference of the underlying data doesn't mean it is removed from the
pointer itself, or de-allocated after Ref<T>
goes out of scope.
Another thread can of course swap the data contained in the pointer,
which is why compare_exchange
requires a previously held data
reference.