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

Don't inherit Send from parking_lot::*Guard #4359

Merged
merged 6 commits into from Dec 31, 2021
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
15 changes: 15 additions & 0 deletions .github/workflows/ci.yml
Expand Up @@ -20,6 +20,7 @@ jobs:
needs:
- test
- test-unstable
- test-parking_lot
- miri
- cross
- features
Expand Down Expand Up @@ -77,6 +78,20 @@ jobs:
# bench.yml workflow runs benchmarks only on linux.
if: startsWith(matrix.os, 'ubuntu')

test-parking_lot:
name: compile tests with parking lot send guards
Darksonn marked this conversation as resolved.
Show resolved Hide resolved
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Install Rust
run: rustup update stable
- uses: Swatinem/rust-cache@v1
- name: Enable parking_lot send_guard feature
# Inserts the line "plsend = ["parking_lot/send_guard"]" right after [features]
run: sed -i '/\[features\]/a plsend = ["parking_lot/send_guard"]' tokio/Cargo.toml
- name: Compile tests with all features enabled
run: cargo build --workspace --all-features --tests

valgrind:
name: valgrind
runs-on: ubuntu-latest
Expand Down
91 changes: 72 additions & 19 deletions tokio/src/loom/std/parking_lot.rs
Expand Up @@ -3,91 +3,144 @@
//!
//! This can be extended to additional types/methods as required.

use std::marker::PhantomData;
use std::ops::{Deref, DerefMut};
use std::sync::LockResult;
use std::time::Duration;

// Types that do not need wrapping
pub(crate) use parking_lot::{MutexGuard, RwLockReadGuard, RwLockWriteGuard, WaitTimeoutResult};
pub(crate) use parking_lot::WaitTimeoutResult;

/// Adapter for `parking_lot::Mutex` to the `std::sync::Mutex` interface.
#[derive(Debug)]
pub(crate) struct Mutex<T: ?Sized>(parking_lot::Mutex<T>);
pub(crate) struct Mutex<T: ?Sized>(PhantomData<std::sync::Mutex<T>>, parking_lot::Mutex<T>);

#[derive(Debug)]
pub(crate) struct RwLock<T>(parking_lot::RwLock<T>);
pub(crate) struct RwLock<T>(PhantomData<std::sync::RwLock<T>>, parking_lot::RwLock<T>);
Copy link
Member

Choose a reason for hiding this comment

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

i have a slight preference for either making these named fields, or breaking them across multiple lines like we do with the guard types...this feels like a lot for one line. not a blocker though.


/// Adapter for `parking_lot::Condvar` to the `std::sync::Condvar` interface.
#[derive(Debug)]
pub(crate) struct Condvar(parking_lot::Condvar);
pub(crate) struct Condvar(PhantomData<std::sync::Condvar>, parking_lot::Condvar);

#[derive(Debug)]
pub(crate) struct MutexGuard<'a, T: ?Sized>(
PhantomData<std::sync::MutexGuard<'a, T>>,
hawkw marked this conversation as resolved.
Show resolved Hide resolved
parking_lot::MutexGuard<'a, T>,
);

#[derive(Debug)]
pub(crate) struct RwLockReadGuard<'a, T: ?Sized>(
PhantomData<std::sync::RwLockReadGuard<'a, T>>,
parking_lot::RwLockReadGuard<'a, T>,
);

#[derive(Debug)]
pub(crate) struct RwLockWriteGuard<'a, T: ?Sized>(
PhantomData<std::sync::RwLockWriteGuard<'a, T>>,
parking_lot::RwLockWriteGuard<'a, T>,
);

impl<T> Mutex<T> {
#[inline]
pub(crate) fn new(t: T) -> Mutex<T> {
Mutex(parking_lot::Mutex::new(t))
Mutex(PhantomData, parking_lot::Mutex::new(t))
}

#[inline]
#[cfg(all(feature = "parking_lot", not(all(loom, test)),))]
#[cfg_attr(docsrs, doc(cfg(all(feature = "parking_lot",))))]
pub(crate) const fn const_new(t: T) -> Mutex<T> {
Mutex(parking_lot::const_mutex(t))
Mutex(PhantomData, parking_lot::const_mutex(t))
}

#[inline]
pub(crate) fn lock(&self) -> MutexGuard<'_, T> {
self.0.lock()
MutexGuard(PhantomData, self.1.lock())
}

#[inline]
pub(crate) fn try_lock(&self) -> Option<MutexGuard<'_, T>> {
self.0.try_lock()
self.1
.try_lock()
.map(|guard| MutexGuard(PhantomData, guard))
}

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

// Note: Additional methods `is_poisoned` and `into_inner`, can be
// provided here as needed.
}

impl<'a, T: ?Sized> Deref for MutexGuard<'a, T> {
type Target = T;
fn deref(&self) -> &T {
self.1.deref()
}
}

impl<'a, T: ?Sized> DerefMut for MutexGuard<'a, T> {
fn deref_mut(&mut self) -> &mut T {
self.1.deref_mut()
}
}

impl<T> RwLock<T> {
pub(crate) fn new(t: T) -> RwLock<T> {
RwLock(parking_lot::RwLock::new(t))
RwLock(PhantomData, parking_lot::RwLock::new(t))
}

pub(crate) fn read(&self) -> LockResult<RwLockReadGuard<'_, T>> {
Ok(self.0.read())
Ok(RwLockReadGuard(PhantomData, self.1.read()))
}

pub(crate) fn write(&self) -> LockResult<RwLockWriteGuard<'_, T>> {
Ok(self.0.write())
Ok(RwLockWriteGuard(PhantomData, self.1.write()))
}
}

impl<'a, T: ?Sized> Deref for RwLockReadGuard<'a, T> {
type Target = T;
fn deref(&self) -> &T {
self.1.deref()
}
}

impl<'a, T: ?Sized> Deref for RwLockWriteGuard<'a, T> {
type Target = T;
fn deref(&self) -> &T {
self.1.deref()
}
}

impl<'a, T: ?Sized> DerefMut for RwLockWriteGuard<'a, T> {
fn deref_mut(&mut self) -> &mut T {
self.1.deref_mut()
}
}

impl Condvar {
#[inline]
pub(crate) fn new() -> Condvar {
Condvar(parking_lot::Condvar::new())
Condvar(PhantomData, parking_lot::Condvar::new())
}

#[inline]
pub(crate) fn notify_one(&self) {
self.0.notify_one();
self.1.notify_one();
}

#[inline]
pub(crate) fn notify_all(&self) {
self.0.notify_all();
self.1.notify_all();
}

#[inline]
pub(crate) fn wait<'a, T>(
&self,
mut guard: MutexGuard<'a, T>,
) -> LockResult<MutexGuard<'a, T>> {
self.0.wait(&mut guard);
self.1.wait(&mut guard.1);
Ok(guard)
}

Expand All @@ -97,7 +150,7 @@ impl Condvar {
mut guard: MutexGuard<'a, T>,
timeout: Duration,
) -> LockResult<(MutexGuard<'a, T>, WaitTimeoutResult)> {
let wtr = self.0.wait_for(&mut guard, timeout);
let wtr = self.1.wait_for(&mut guard.1, timeout);
Ok((guard, wtr))
}

Expand Down