Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add an AtomicCell abstraction #62577

Merged
merged 1 commit into from
Jul 13, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Cargo.lock
Original file line number Diff line number Diff line change
Expand Up @@ -3019,6 +3019,7 @@ name = "rustc_data_structures"
version = "0.0.0"
dependencies = [
"cfg-if 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)",
"crossbeam-utils 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)",
"ena 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)",
"graphviz 0.0.0",
"indexmap 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
Expand Down
1 change: 1 addition & 0 deletions src/librustc_data_structures/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ lazy_static = "1"
serialize = { path = "../libserialize" }
graphviz = { path = "../libgraphviz" }
cfg-if = "0.1.2"
crossbeam-utils = { version = "0.6.5", features = ["nightly"] }
stable_deref_trait = "1.0.0"
rayon = { version = "0.2.0", package = "rustc-rayon" }
rayon-core = { version = "0.2.0", package = "rustc-rayon-core" }
Expand Down
55 changes: 54 additions & 1 deletion src/librustc_data_structures/sync.rs
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,51 @@ cfg_if! {
use std::ops::Add;
use std::panic::{resume_unwind, catch_unwind, AssertUnwindSafe};

/// This is a single threaded variant of AtomicCell provided by crossbeam.
/// Unlike `Atomic` this is intended for all `Copy` types,
/// but it lacks the explicit ordering arguments.
#[derive(Debug)]
pub struct AtomicCell<T: Copy>(Cell<T>);

impl<T: Copy> AtomicCell<T> {
#[inline]
pub fn new(v: T) -> Self {
AtomicCell(Cell::new(v))
}

#[inline]
pub fn get_mut(&mut self) -> &mut T {
self.0.get_mut()
}
}

impl<T: Copy> AtomicCell<T> {
#[inline]
pub fn into_inner(self) -> T {
self.0.into_inner()
}

#[inline]
pub fn load(&self) -> T {
self.0.get()
}

#[inline]
pub fn store(&self, val: T) {
self.0.set(val)
}

#[inline]
pub fn swap(&self, val: T) -> T {
self.0.replace(val)
}
}

/// This is a single threaded variant of `AtomicU64`, `AtomicUsize`, etc.
/// It differs from `AtomicCell` in that it has explicit ordering arguments
/// and is only intended for use with the native atomic types.
/// You should use this type through the `AtomicU64`, `AtomicUsize`, etc, type aliases
/// as it's not intended to be used separately.
#[derive(Debug)]
pub struct Atomic<T: Copy>(Cell<T>);

Expand All @@ -77,7 +122,8 @@ cfg_if! {
}
}

impl<T: Copy + PartialEq> Atomic<T> {
impl<T: Copy> Atomic<T> {
#[inline]
pub fn into_inner(self) -> T {
self.0.into_inner()
}
Expand All @@ -92,10 +138,14 @@ cfg_if! {
self.0.set(val)
}

#[inline]
pub fn swap(&self, val: T, _: Ordering) -> T {
self.0.replace(val)
}
}

impl<T: Copy + PartialEq> Atomic<T> {
#[inline]
pub fn compare_exchange(&self,
current: T,
new: T,
Expand All @@ -113,6 +163,7 @@ cfg_if! {
}

impl<T: Add<Output=T> + Copy> Atomic<T> {
#[inline]
pub fn fetch_add(&self, val: T, _: Ordering) -> T {
let old = self.0.get();
self.0.set(old + val);
Expand Down Expand Up @@ -271,6 +322,8 @@ cfg_if! {

pub use std::sync::atomic::{AtomicBool, AtomicUsize, AtomicU32, AtomicU64};

pub use crossbeam_utils::atomic::AtomicCell;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't get why you define the struct AtomicCell above but then use it from the crossbeam_utils? Are they different? What is the purpose of including AtomicCell from crossbeam_utils here?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In general, this code defines a unified set of structures related to multi-threadiness(?) with a caveat - the definitions are different for parallel_compiler cfg.

If you expand the omitted lines in the diff, you can see that the pub struct AtomicCell<T: Copy>(Cell<T>); (which is mainly a wrapper around Cell<T>, which isn't really atomic nor should it be in single-threaded case) is defined manually in the #[cfg(not(parallel_compiler))] branch.
Otherwise, if we build a parallel compiler, we just re-export crossbeam_utils::atomic::AtomicCell instead.


pub use std::sync::Arc as Lrc;
pub use std::sync::Weak as Weak;

Expand Down