chore: unify all mocked loom files (#1732)

When the crates were merged, each component kept its own `loom` file
containing mocked types it needed. This patch unifies them all in one
location.
This commit is contained in:
Carl Lerche
2019-11-04 22:22:40 -08:00
committed by GitHub
parent 94f9b04b06
commit a6253ed05a
48 changed files with 134 additions and 241 deletions
+1 -1
View File
@@ -1,5 +1,5 @@
use crate::executor::blocking::Pool;
use crate::executor::loom::thread;
use crate::loom::thread;
use std::usize;
+2 -2
View File
@@ -1,7 +1,7 @@
//! Thread pool for blocking operations
use crate::executor::loom::sync::{Arc, Condvar, Mutex};
use crate::executor::loom::thread;
use crate::loom::sync::{Arc, Condvar, Mutex};
use crate::loom::thread;
#[cfg(feature = "blocking")]
use crate::sync::oneshot;
-30
View File
@@ -1,30 +0,0 @@
//! Stub out the necessary APIs to model with loom.
#[cfg(not(all(test, loom)))]
pub(crate) mod std;
#[cfg(all(test, loom))]
pub(crate) mod std {
pub(crate) use loom::{alloc, cell, sync, thread};
pub(crate) mod rand {
pub(crate) fn seed() -> u64 {
1
}
}
pub(crate) mod sys {
pub(crate) fn num_cpus() -> usize {
2
}
}
}
#[cfg(feature = "rt-full")]
pub(crate) use self::std::rand;
#[cfg(any(feature = "blocking", feature = "rt-current-thread"))]
pub(crate) use self::std::sync;
#[cfg(any(feature = "blocking", feature = "rt-full"))]
pub(crate) use self::std::thread;
#[cfg(feature = "rt-current-thread")]
pub(crate) use self::std::{alloc, cell, sys};
-2
View File
@@ -52,8 +52,6 @@ pub(crate) use self::enter::enter;
mod global;
pub use self::global::spawn;
pub(crate) mod loom;
pub mod park;
#[cfg(feature = "rt-current-thread")]
+3 -3
View File
@@ -1,6 +1,6 @@
use crate::executor::loom::sync::atomic::AtomicUsize;
use crate::executor::loom::sync::{Arc, Condvar, Mutex};
use crate::executor::park::{Park, Unpark};
use crate::loom::sync::atomic::AtomicUsize;
use crate::loom::sync::{Arc, Condvar, Mutex};
use std::marker::PhantomData;
use std::rc::Rc;
@@ -213,7 +213,7 @@ impl Unpark for UnparkThread {
#[cfg(feature = "rt-full")]
mod waker {
use super::{Inner, UnparkThread};
use crate::executor::loom::sync::Arc;
use crate::loom::sync::Arc;
use std::mem;
use std::task::{RawWaker, RawWakerVTable, Waker};
+2 -2
View File
@@ -1,9 +1,9 @@
use crate::executor::loom::alloc::Track;
use crate::executor::loom::cell::CausalCell;
use crate::executor::task::raw::{self, Vtable};
use crate::executor::task::state::State;
use crate::executor::task::waker::waker_ref;
use crate::executor::task::Schedule;
use crate::loom::alloc::Track;
use crate::loom::cell::CausalCell;
use std::cell::UnsafeCell;
use std::future::Future;
+2 -2
View File
@@ -1,8 +1,8 @@
use crate::executor::loom::alloc::Track;
use crate::executor::loom::cell::CausalCheck;
use crate::executor::task::core::{Cell, Core, Header, Trailer};
use crate::executor::task::state::Snapshot;
use crate::executor::task::{JoinError, Schedule, Task};
use crate::loom::alloc::Track;
use crate::loom::cell::CausalCheck;
use std::future::Future;
use std::marker::PhantomData;
+1 -1
View File
@@ -1,5 +1,5 @@
use crate::executor::loom::alloc::Track;
use crate::executor::task::raw::RawTask;
use crate::loom::alloc::Track;
use std::fmt;
use std::future::Future;
+1 -1
View File
@@ -1,8 +1,8 @@
use crate::executor::loom::alloc::Track;
use crate::executor::task::core::Cell;
use crate::executor::task::harness::Harness;
use crate::executor::task::state::{Snapshot, State};
use crate::executor::task::{Header, Schedule};
use crate::loom::alloc::Track;
use std::future::Future;
use std::ptr::NonNull;
+1 -1
View File
@@ -1,5 +1,5 @@
use crate::executor::loom::sync::atomic::AtomicPtr;
use crate::executor::task::{Header, Task};
use crate::loom::sync::atomic::AtomicPtr;
use std::marker::PhantomData;
use std::ptr::{self, NonNull};
+5 -5
View File
@@ -1,4 +1,4 @@
use crate::executor::loom::sync::atomic::AtomicUsize;
use crate::loom::sync::atomic::AtomicUsize;
use std::fmt;
use std::sync::atomic::Ordering::{AcqRel, Acquire, Release};
@@ -224,7 +224,7 @@ impl State {
///
/// Returns a snapshot of the state **after** the transition.
pub(super) fn release_task(&self) -> Snapshot {
use crate::executor::loom::sync::atomic;
use crate::loom::sync::atomic;
const DELTA: usize = RELEASED;
@@ -283,7 +283,7 @@ impl State {
///
/// Returns a snapshot of the state **after** the transition.
pub(super) fn complete_join_handle(&self) -> Snapshot {
use crate::executor::loom::sync::atomic;
use crate::loom::sync::atomic;
const DELTA: usize = JOIN_INTEREST;
@@ -337,7 +337,7 @@ impl State {
/// Store the join waker.
pub(super) fn store_join_waker(&self) -> Snapshot {
use crate::executor::loom::sync::atomic;
use crate::loom::sync::atomic;
const DELTA: usize = JOIN_WAKER;
@@ -407,7 +407,7 @@ impl State {
/// Returns `true` if the task should be released.
pub(super) fn ref_dec(&self) -> bool {
use crate::executor::loom::sync::atomic;
use crate::loom::sync::atomic;
let prev = self.val.fetch_sub(WAKER_ONE, Release);
let next = Snapshot(prev - WAKER_ONE);
+3 -4
View File
@@ -1,8 +1,7 @@
use crate::executor::loom::sync::Arc;
use crate::executor::loom::sys::num_cpus;
use crate::executor::loom::thread;
use crate::executor::park::Park;
use crate::executor::thread_pool::{shutdown, worker, worker::Worker, Spawner, ThreadPool};
use crate::loom::sync::Arc;
use crate::loom::sys::num_cpus;
use std::{fmt, usize};
@@ -109,7 +108,7 @@ impl Builder {
impl Drop for AbortOnPanic {
fn drop(&mut self) {
if thread::panicking() {
if std::thread::panicking() {
eprintln!("[ERROR] unhandled panic in Tokio scheduler. This is a bug and should be reported.");
std::process::abort();
}
+1 -1
View File
@@ -1,6 +1,6 @@
use crate::executor::loom::sync::Arc;
use crate::executor::park::Unpark;
use crate::executor::thread_pool::{worker, Owned};
use crate::loom::sync::Arc;
use std::cell::Cell;
use std::ptr;
+2 -2
View File
@@ -1,7 +1,7 @@
//! Coordinates idling workers
use crate::executor::loom::sync::atomic::AtomicUsize;
use crate::executor::loom::sync::Mutex;
use crate::loom::sync::atomic::AtomicUsize;
use crate::loom::sync::Mutex;
use std::fmt;
use std::sync::atomic::Ordering::{self, AcqRel, Relaxed, SeqCst};
@@ -1,6 +1,6 @@
use crate::executor::loom::sync::atomic::AtomicUsize;
use crate::executor::loom::sync::Mutex;
use crate::executor::task::{Header, Task};
use crate::loom::sync::atomic::AtomicUsize;
use crate::loom::sync::Mutex;
use std::marker::PhantomData;
use std::ptr::{self, NonNull};
@@ -1,6 +1,6 @@
use crate::executor::loom::sync::Arc;
use crate::executor::task::Task;
use crate::executor::thread_pool::queue::Cluster;
use crate::loom::sync::Arc;
pub(crate) struct Inject<T: 'static> {
cluster: Arc<Cluster<T>>,
@@ -1,8 +1,8 @@
use crate::executor::loom::cell::{CausalCell, CausalCheck};
use crate::executor::loom::sync::atomic::{self, AtomicU32};
use crate::executor::task::Task;
use crate::executor::thread_pool::queue::global;
use crate::executor::thread_pool::LOCAL_QUEUE_CAPACITY;
use crate::loom::cell::{CausalCell, CausalCheck};
use crate::loom::sync::atomic::{self, AtomicU32};
use std::fmt;
use std::mem::MaybeUninit;
+1 -1
View File
@@ -8,7 +8,7 @@ mod worker;
pub(crate) use self::inject::Inject;
pub(crate) use self::worker::Worker;
use crate::executor::loom::sync::Arc;
use crate::loom::sync::Arc;
pub(crate) fn build<T: 'static>(workers: usize) -> Vec<Worker<T>> {
let local: Vec<_> = (0..workers).map(|_| local::Queue::new()).collect();
@@ -1,6 +1,6 @@
use crate::executor::loom::sync::Arc;
use crate::executor::task::Task;
use crate::executor::thread_pool::queue::{local, Cluster, Inject};
use crate::loom::sync::Arc;
use std::cell::Cell;
use std::fmt;
+2 -2
View File
@@ -2,12 +2,12 @@
//!
//! - Attempt to spin.
use crate::executor::loom::rand::seed;
use crate::executor::loom::sync::Arc;
use crate::executor::park::Unpark;
use crate::executor::task::{self, JoinHandle, Task};
use crate::executor::thread_pool::{current, queue, Idle, Owned, Shared};
use crate::executor::util::{CachePadded, FastRand};
use crate::loom::rand::seed;
use crate::loom::sync::Arc;
use std::cell::UnsafeCell;
use std::future::Future;
+1 -1
View File
@@ -3,7 +3,7 @@
//! Each worker holds the `Sender` half. When all the `Sender` halves are
//! dropped, the `Receiver` receives a notification.
use crate::executor::loom::sync::Arc;
use crate::loom::sync::Arc;
use crate::sync::oneshot;
#[derive(Debug, Clone)]
+1 -1
View File
@@ -1,7 +1,7 @@
use crate::executor::loom::sync::Arc;
use crate::executor::park::Unpark;
use crate::executor::task::JoinHandle;
use crate::executor::thread_pool::worker;
use crate::loom::sync::Arc;
use std::fmt;
use std::future::Future;
@@ -1,14 +1,13 @@
use crate::executor::loom::sync::atomic::Ordering::{Acquire, Relaxed, Release};
use crate::executor::loom::sync::atomic::{AtomicBool, AtomicUsize};
use crate::executor::loom::sync::{Arc, Mutex};
use crate::executor::park::{Park, Unpark};
use crate::executor::tests::loom_oneshot as oneshot;
use crate::executor::thread_pool::{self, Builder};
use crate::spawn;
use loom::sync::Notify;
use loom::sync::atomic::{AtomicBool, AtomicUsize};
use loom::sync::{Arc, Mutex, Notify};
use std::future::Future;
use std::sync::atomic::Ordering::{Acquire, Relaxed, Release};
use std::time::Duration;
#[test]
@@ -190,7 +189,7 @@ fn gated() -> impl Future<Output = &'static str> {
}
fn gated2(thread: bool) -> impl Future<Output = &'static str> {
use crate::executor::loom::thread;
use loom::thread;
use std::sync::Arc;
let gate = Arc::new(AtomicBool::new(false));
+1 -1
View File
@@ -1,7 +1,7 @@
use crate::executor::loom::sync::Arc;
use crate::executor::park::{Park, Unpark};
use crate::executor::task::Task;
use crate::executor::thread_pool::{current, Owned, Shared, Spawner};
use crate::loom::sync::Arc;
use std::cell::Cell;
use std::ops::{Deref, DerefMut};
+1 -1
View File
@@ -98,7 +98,7 @@ pub mod io;
#[cfg(feature = "net-driver")]
pub mod net;
#[cfg(feature = "net-driver")]
#[cfg(any(feature = "sync", feature = "blocking", feature = "rt-current-thread"))]
mod loom;
pub mod prelude;
-45
View File
@@ -1,45 +0,0 @@
//! This module abstracts over `loom` and `std::sync` depending on whether we
//! are running tests or not.
pub(crate) use self::inner::*;
#[cfg(all(test, loom))]
mod inner {
pub(crate) use loom::sync::CausalCell;
pub(crate) use loom::sync::Mutex;
pub(crate) mod atomic {
pub(crate) use loom::sync::atomic::*;
pub(crate) use std::sync::atomic::Ordering;
}
}
#[cfg(not(all(test, loom)))]
mod inner {
use std::cell::UnsafeCell;
pub(crate) use std::sync::atomic;
pub(crate) use std::sync::Mutex;
#[derive(Debug)]
pub(crate) struct CausalCell<T>(UnsafeCell<T>);
impl<T> CausalCell<T> {
pub(crate) fn new(data: T) -> CausalCell<T> {
CausalCell(UnsafeCell::new(data))
}
#[inline(always)]
pub(crate) fn with<F, R>(&self, f: F) -> R
where
F: FnOnce(*const T) -> R,
{
f(self.0.get())
}
#[inline(always)]
pub(crate) fn with_mut<F, R>(&self, f: F) -> R
where
F: FnOnce(*mut T) -> R,
{
f(self.0.get())
}
}
}
+13
View File
@@ -0,0 +1,13 @@
pub(crate) use loom::*;
pub(crate) mod rand {
pub(crate) fn seed() -> u64 {
1
}
}
pub(crate) mod sys {
pub(crate) fn num_cpus() -> usize {
2
}
}
+12
View File
@@ -0,0 +1,12 @@
//! This module abstracts over `loom` and `std::sync` depending on whether we
//! are running tests or not.
#[cfg(not(all(test, loom)))]
mod std;
#[cfg(not(all(test, loom)))]
pub(crate) use self::std::*;
#[cfg(all(test, loom))]
mod mocked;
#[cfg(all(test, loom))]
pub(crate) use self::mocked::*;
+18
View File
@@ -0,0 +1,18 @@
#[derive(Debug)]
pub(crate) struct Track<T> {
value: T,
}
impl<T> Track<T> {
pub(crate) fn new(value: T) -> Track<T> {
Track { value }
}
pub(crate) fn get_mut(&mut self) -> &mut T {
&mut self.value
}
pub(crate) fn into_inner(self) -> T {
self.value
}
}
@@ -1,6 +1,6 @@
use std::cell::UnsafeCell;
use std::fmt;
use std::ops::Deref;
use std::ops;
/// `AtomicUsize` providing an additional `load_unsync` function.
pub(crate) struct AtomicUsize {
@@ -11,7 +11,6 @@ unsafe impl Send for AtomicUsize {}
unsafe impl Sync for AtomicUsize {}
impl AtomicUsize {
#[cfg(feature = "rt-current-thread")]
pub(crate) fn new(val: usize) -> AtomicUsize {
let inner = UnsafeCell::new(std::sync::atomic::AtomicUsize::new(val));
AtomicUsize { inner }
@@ -23,13 +22,12 @@ impl AtomicUsize {
///
/// All mutations must have happened before the unsynchronized load.
/// Additionally, there must be no concurrent mutations.
#[cfg(feature = "rt-full")]
pub(crate) unsafe fn unsync_load(&self) -> usize {
*(*self.inner.get()).get_mut()
}
}
impl Deref for AtomicUsize {
impl ops::Deref for AtomicUsize {
type Target = std::sync::atomic::AtomicUsize;
fn deref(&self) -> &Self::Target {
@@ -39,8 +37,15 @@ impl Deref for AtomicUsize {
}
}
impl fmt::Debug for AtomicUsize {
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
self.deref().fmt(fmt)
impl ops::DerefMut for AtomicUsize {
fn deref_mut(&mut self) -> &mut Self::Target {
// safety: we hold `&mut self`
unsafe { &mut *self.inner.get() }
}
}
impl fmt::Debug for AtomicUsize {
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
(**self).fmt(fmt)
}
}
@@ -1,5 +1,6 @@
use std::cell::UnsafeCell;
#[derive(Debug)]
pub(crate) struct CausalCell<T>(UnsafeCell<T>);
#[derive(Default)]
@@ -44,6 +45,5 @@ impl<T> CausalCell<T> {
impl CausalCheck {
pub(crate) fn check(self) {}
#[cfg(feature = "rt-full")]
pub(crate) fn join(&mut self, _other: CausalCheck) {}
}
@@ -1,39 +1,21 @@
// rt-full implies rt-current-thread
#[cfg(feature = "rt-full")]
#![cfg_attr(not(feature = "rt-full"), allow(unused_imports, dead_code))]
mod atomic_u32;
mod atomic_usize;
#[cfg(feature = "rt-current-thread")]
mod causal_cell;
#[cfg(feature = "rt-current-thread")]
pub(crate) mod alloc {
#[derive(Debug)]
pub(crate) struct Track<T> {
value: T,
}
pub(crate) mod alloc;
impl<T> Track<T> {
pub(crate) fn new(value: T) -> Track<T> {
Track { value }
}
pub(crate) fn get_mut(&mut self) -> &mut T {
&mut self.value
}
pub(crate) fn into_inner(self) -> T {
self.value
}
}
}
#[cfg(feature = "rt-current-thread")]
pub(crate) mod cell {
pub(crate) use super::causal_cell::{CausalCell, CausalCheck};
}
#[cfg(feature = "rt-full")]
pub(crate) mod future {
pub(crate) use crate::sync::AtomicWaker;
}
pub(crate) mod rand {
use std::collections::hash_map::RandomState;
use std::hash::{BuildHasher, Hash, Hasher};
@@ -56,23 +38,17 @@ pub(crate) mod rand {
}
pub(crate) mod sync {
#[cfg(any(feature = "blocking", feature = "rt-current-thread"))]
pub(crate) use std::sync::{Arc, Condvar, Mutex};
pub(crate) use std::sync::*;
pub(crate) mod atomic {
#[cfg(feature = "rt-full")]
pub(crate) use crate::executor::loom::std::atomic_u32::AtomicU32;
#[cfg(feature = "rt-current-thread")]
pub(crate) use crate::executor::loom::std::atomic_usize::AtomicUsize;
pub(crate) use crate::loom::std::atomic_u32::AtomicU32;
pub(crate) use crate::loom::std::atomic_usize::AtomicUsize;
#[cfg(feature = "rt-full")]
pub(crate) use std::sync::atomic::spin_loop_hint;
#[cfg(feature = "rt-current-thread")]
pub(crate) use std::sync::atomic::{fence, AtomicPtr};
}
}
#[cfg(feature = "rt-current-thread")]
pub(crate) mod sys {
#[cfg(feature = "rt-full")]
pub(crate) fn num_cpus() -> usize {
@@ -85,5 +61,4 @@ pub(crate) mod sys {
}
}
#[cfg(any(feature = "blocking", feature = "rt-full"))]
pub(crate) use std::thread;
@@ -1,5 +1,5 @@
use super::{Pack, INITIAL_PAGE_SIZE, WIDTH};
use crate::loom::CausalCell;
use crate::loom::cell::CausalCell;
pub(crate) mod scheduled_io;
mod stack;
@@ -1,10 +1,9 @@
use super::super::{Pack, Tid, RESERVED_BITS, WIDTH};
use crate::loom::{
atomic::{AtomicUsize, Ordering},
CausalCell,
};
use crate::loom::{cell::CausalCell, sync::atomic::AtomicUsize};
use crate::sync::AtomicWaker;
use std::sync::atomic::Ordering;
#[derive(Debug)]
pub(crate) struct ScheduledIo {
/// The offset of the next item on the free list.
@@ -1,5 +1,7 @@
use crate::loom::atomic::{AtomicUsize, Ordering};
use crate::loom::sync::atomic::AtomicUsize;
use std::fmt;
use std::sync::atomic::Ordering;
pub(super) struct TransferStack {
head: AtomicUsize,
@@ -55,7 +57,7 @@ impl fmt::Debug for TransferStack {
mod test {
use super::super::super::test_util;
use super::*;
use crate::loom::CausalCell;
use loom::cell::CausalCell;
use loom::thread;
use std::sync::Arc;
@@ -1,7 +1,7 @@
use super::*;
use std::fmt;
use crate::loom::Mutex;
use crate::loom::sync::Mutex;
/// A sharded slab.
pub(crate) struct Slab {
+4 -2
View File
@@ -1,6 +1,8 @@
use super::platform;
use crate::executor::park::{Park, Unpark};
use crate::loom::atomic::{AtomicUsize, Ordering::SeqCst};
use crate::loom::sync::atomic::AtomicUsize;
use crate::net::driver::platform;
use std::sync::atomic::Ordering::SeqCst;
mod dispatch;
use dispatch::SingleShard;
+1 -1
View File
@@ -78,7 +78,7 @@ impl Builder {
current_thread: false,
// Default to use an equal number of threads to number of CPU cores
num_threads: crate::executor::loom::sys::num_cpus(),
num_threads: crate::loom::sys::num_cpus(),
// Default thread name
thread_name: "tokio-runtime-worker".into(),
-48
View File
@@ -1,48 +0,0 @@
#[cfg(not(all(test, loom)))]
mod imp {
pub(crate) mod future {
pub(crate) use crate::sync::task::AtomicWaker;
}
pub(crate) mod sync {
pub(crate) use std::sync::atomic;
pub(crate) use std::sync::Arc;
use std::cell::UnsafeCell;
pub(crate) struct CausalCell<T>(UnsafeCell<T>);
impl<T> CausalCell<T> {
pub(crate) fn new(data: T) -> CausalCell<T> {
CausalCell(UnsafeCell::new(data))
}
pub(crate) fn with<F, R>(&self, f: F) -> R
where
F: FnOnce(*const T) -> R,
{
f(self.0.get())
}
pub(crate) fn with_mut<F, R>(&self, f: F) -> R
where
F: FnOnce(*mut T) -> R,
{
f(self.0.get())
}
}
}
pub(crate) mod thread {
pub(crate) fn yield_now() {
::std::sync::atomic::spin_loop_hint();
}
}
}
#[cfg(all(test, loom))]
mod imp {
pub(crate) use loom::*;
}
pub(crate) use self::imp::*;
-2
View File
@@ -37,8 +37,6 @@ macro_rules! if_loom {
mod barrier;
pub use barrier::{Barrier, BarrierWaitResult};
mod loom;
pub mod mpsc;
mod mutex;
+2 -2
View File
@@ -1,6 +1,6 @@
use crate::sync::loom::{
use crate::loom::{
cell::CausalCell,
sync::atomic::{AtomicPtr, AtomicUsize},
sync::CausalCell,
thread,
};
+1 -5
View File
@@ -1,8 +1,4 @@
use crate::sync::loom::{
future::AtomicWaker,
sync::atomic::AtomicUsize,
sync::{Arc, CausalCell},
};
use crate::loom::{cell::CausalCell, future::AtomicWaker, sync::atomic::AtomicUsize, sync::Arc};
use crate::sync::mpsc::list;
use std::fmt;
+1 -1
View File
@@ -1,6 +1,6 @@
//! A concurrent, lock-free, FIFO list.
use crate::sync::loom::{
use crate::loom::{
sync::atomic::{AtomicPtr, AtomicUsize},
thread,
};
+1 -1
View File
@@ -1,4 +1,4 @@
use crate::sync::loom::sync::atomic::AtomicUsize;
use crate::loom::sync::atomic::AtomicUsize;
use crate::sync::mpsc::chan;
use std::fmt;
+3 -1
View File
@@ -1,6 +1,8 @@
//! A channel for sending a single message between asynchronous tasks.
use crate::sync::loom::sync::{atomic::AtomicUsize, Arc, CausalCell};
use crate::loom::cell::CausalCell;
use crate::loom::sync::atomic::AtomicUsize;
use crate::loom::sync::Arc;
use futures_core::ready;
use std::fmt;
+3 -5
View File
@@ -8,12 +8,10 @@
//! section. If no permits are available, then acquiring the semaphore returns
//! `Pending`. The task is woken once a permit becomes available.
use crate::sync::loom::{
use crate::loom::{
cell::CausalCell,
future::AtomicWaker,
sync::{
atomic::{AtomicPtr, AtomicUsize},
CausalCell,
},
sync::atomic::{AtomicPtr, AtomicUsize},
thread,
};
+2 -2
View File
@@ -1,5 +1,5 @@
use crate::sync::loom::sync::atomic::{self, AtomicUsize};
use crate::sync::loom::sync::CausalCell;
use crate::loom::cell::CausalCell;
use crate::loom::sync::atomic::{self, AtomicUsize};
use std::fmt;
use std::sync::atomic::Ordering::{AcqRel, Acquire, Release};