Skip to content

Commit

Permalink
sync: Implement map methods of parking_lot fame
Browse files Browse the repository at this point in the history
I've introduced `MappedRwLockReadGuard` and `MappedRwLockWriteGuard`,
which are produced by the relevant `map` and `try_map` methods.

Generally, this mimics the way `MappedRwLock*Guard`s are implemented in
`parking_lot`. By storing a raw pointer in the guards themselves
referencing the mapped data and maintaining type invariants through
`PhantomData`. I didn't try to think too much about this, so if someone
has objections I'd love to hear them.

I've also dropped the internal use of `ReleasingPermit`, since it made
the guards unecessarily large. The number of permits that need to be
released are already known by the guards themselves, and is instead
governed directly in the relevant `Drop` impls.  This has the benefit of
making the guards as small as possible, for the non-mapped variants this
means a single reference is enough.

`fmt::Debug` impls have been adjusted to behave exactly like the
delegating impls in `parking_lot`. `fmt::Display` impls have been added
for all guard types which behave the same. This does change the format
of debug impls, for which I'm not sure if we provide any guarantees.
  • Loading branch information
udoprog committed May 7, 2020
1 parent 4748b25 commit b4d2d25
Show file tree
Hide file tree
Showing 6 changed files with 640 additions and 37 deletions.
24 changes: 18 additions & 6 deletions tokio-macros/src/entry.rs
Expand Up @@ -65,7 +65,7 @@ fn parse_knobs(
return Err(syn::Error::new_spanned(
namevalue,
"core_threads argument must be an int",
))
));
}
}
} else {
Expand Down Expand Up @@ -93,11 +93,14 @@ fn parse_knobs(
return Err(syn::Error::new_spanned(
namevalue,
"max_threads argument must be an int",
))
));
}
},
name => {
let msg = format!("Unknown attribute pair {} is specified; expected one of: `core_threads`, `max_threads`", name);
let msg = format!(
"Unknown attribute pair {} is specified; expected one of: `core_threads`, `max_threads`",
name
);
return Err(syn::Error::new_spanned(namevalue, msg));
}
}
Expand All @@ -114,7 +117,10 @@ fn parse_knobs(
}
"basic_scheduler" => runtime = Some(runtime.unwrap_or_else(|| Runtime::Basic)),
name => {
let msg = format!("Unknown attribute {} is specified; expected `basic_scheduler` or `threaded_scheduler`", name);
let msg = format!(
"Unknown attribute {} is specified; expected `basic_scheduler` or `threaded_scheduler`",
name
);
return Err(syn::Error::new_spanned(path, msg));
}
}
Expand Down Expand Up @@ -251,7 +257,10 @@ pub(crate) mod old {
"threaded_scheduler" => runtime = Runtime::Threaded,
"basic_scheduler" => runtime = Runtime::Basic,
name => {
let msg = format!("Unknown attribute {} is specified; expected `basic_scheduler` or `threaded_scheduler`", name);
let msg = format!(
"Unknown attribute {} is specified; expected `basic_scheduler` or `threaded_scheduler`",
name
);
return syn::Error::new_spanned(path, msg).to_compile_error().into();
}
}
Expand Down Expand Up @@ -325,7 +334,10 @@ pub(crate) mod old {
"threaded_scheduler" => runtime = Runtime::Threaded,
"basic_scheduler" => runtime = Runtime::Basic,
name => {
let msg = format!("Unknown attribute {} is specified; expected `basic_scheduler` or `threaded_scheduler`", name);
let msg = format!(
"Unknown attribute {} is specified; expected `basic_scheduler` or `threaded_scheduler`",
name
);
return syn::Error::new_spanned(path, msg).to_compile_error().into();
}
}
Expand Down
5 changes: 4 additions & 1 deletion tokio/src/io/async_read.rs
Expand Up @@ -124,7 +124,10 @@ pub trait AsyncRead {
let b = &mut *(b as *mut [MaybeUninit<u8>] as *mut [u8]);

let n = ready!(self.poll_read(cx, b))?;
assert!(n <= b.len(), "Bad AsyncRead implementation, more bytes were reported as read than the buffer can hold");
assert!(
n <= b.len(),
"Bad AsyncRead implementation, more bytes were reported as read than the buffer can hold"
);
n
};

Expand Down
4 changes: 2 additions & 2 deletions tokio/src/loom/std/mod.rs
@@ -1,10 +1,10 @@
#![cfg_attr(any(not(feature = "full"), loom), allow(unused_imports, dead_code))]

mod atomic_ptr;
mod atomic_u8;
mod atomic_u16;
mod atomic_u32;
mod atomic_u64;
mod atomic_u8;
mod atomic_usize;
#[cfg(feature = "parking_lot")]
mod parking_lot;
Expand Down Expand Up @@ -61,10 +61,10 @@ pub(crate) mod sync {

pub(crate) mod atomic {
pub(crate) use crate::loom::std::atomic_ptr::AtomicPtr;
pub(crate) use crate::loom::std::atomic_u8::AtomicU8;
pub(crate) use crate::loom::std::atomic_u16::AtomicU16;
pub(crate) use crate::loom::std::atomic_u32::AtomicU32;
pub(crate) use crate::loom::std::atomic_u64::AtomicU64;
pub(crate) use crate::loom::std::atomic_u8::AtomicU8;
pub(crate) use crate::loom::std::atomic_usize::AtomicUsize;

pub(crate) use std::sync::atomic::{spin_loop_hint, AtomicBool};
Expand Down
2 changes: 1 addition & 1 deletion tokio/src/sync/mod.rs
Expand Up @@ -446,7 +446,7 @@ cfg_sync! {
pub use semaphore::{Semaphore, SemaphorePermit, OwnedSemaphorePermit};

mod rwlock;
pub use rwlock::{RwLock, RwLockReadGuard, RwLockWriteGuard};
pub use rwlock::{RwLock, RwLockReadGuard, RwLockWriteGuard, MappedRwLockReadGuard, MappedRwLockWriteGuard};

mod task;
pub(crate) use task::AtomicWaker;
Expand Down

0 comments on commit b4d2d25

Please sign in to comment.