Skip to content

Commit

Permalink
Merge pull request #49 from tokio-rs/master
Browse files Browse the repository at this point in the history
task: remove mutex in JoinError (tokio-rs#3959)
  • Loading branch information
sthagen committed Jul 16, 2021
2 parents 810bf27 + aef2d64 commit d66a3a5
Show file tree
Hide file tree
Showing 4 changed files with 35 additions and 4 deletions.
9 changes: 5 additions & 4 deletions tokio/src/runtime/task/error.rs
@@ -1,7 +1,8 @@
use std::any::Any;
use std::fmt;
use std::io;
use std::sync::Mutex;

use crate::util::SyncWrapper;

cfg_rt! {
/// Task failed to execute to completion.
Expand All @@ -12,7 +13,7 @@ cfg_rt! {

enum Repr {
Cancelled,
Panic(Mutex<Box<dyn Any + Send + 'static>>),
Panic(SyncWrapper<Box<dyn Any + Send + 'static>>),
}

impl JoinError {
Expand All @@ -24,7 +25,7 @@ impl JoinError {

pub(crate) fn panic(err: Box<dyn Any + Send + 'static>) -> JoinError {
JoinError {
repr: Repr::Panic(Mutex::new(err)),
repr: Repr::Panic(SyncWrapper::new(err)),
}
}

Expand Down Expand Up @@ -106,7 +107,7 @@ impl JoinError {
/// ```
pub fn try_into_panic(self) -> Result<Box<dyn Any + Send + 'static>, JoinError> {
match self.repr {
Repr::Panic(p) => Ok(p.into_inner().expect("Extracting panic from mutex")),
Repr::Panic(p) => Ok(p.into_inner()),
_ => Err(self),
}
}
Expand Down
3 changes: 3 additions & 0 deletions tokio/src/util/mod.rs
Expand Up @@ -21,6 +21,9 @@ cfg_rt! {
mod wake;
pub(crate) use wake::WakerRef;
pub(crate) use wake::{waker_ref, Wake};

mod sync_wrapper;
pub(crate) use sync_wrapper::SyncWrapper;
}

cfg_rt_multi_thread! {
Expand Down
26 changes: 26 additions & 0 deletions tokio/src/util/sync_wrapper.rs
@@ -0,0 +1,26 @@
//! This module contains a type that can make `Send + !Sync` types `Sync` by
//! disallowing all immutable access to the value.
//!
//! A similar primitive is provided in the `sync_wrapper` crate.

pub(crate) struct SyncWrapper<T> {
value: T,
}

// safety: The SyncWrapper being send allows you to send the inner value across
// thread boundaries.
unsafe impl<T: Send> Send for SyncWrapper<T> {}

// safety: An immutable reference to a SyncWrapper is useless, so moving such an
// immutable reference across threads is safe.
unsafe impl<T> Sync for SyncWrapper<T> {}

impl<T> SyncWrapper<T> {
pub(crate) fn new(value: T) -> Self {
Self { value }
}

pub(crate) fn into_inner(self) -> T {
self.value
}
}
1 change: 1 addition & 0 deletions tokio/tests/async_send_sync.rs
Expand Up @@ -452,6 +452,7 @@ assert_value!(tokio::task::LocalSet: !Send & !Sync & Unpin);
assert_value!(tokio::task::JoinHandle<YY>: Send & Sync & Unpin);
assert_value!(tokio::task::JoinHandle<YN>: Send & Sync & Unpin);
assert_value!(tokio::task::JoinHandle<NN>: !Send & !Sync & Unpin);
assert_value!(tokio::task::JoinError: Send & Sync & Unpin);

assert_value!(tokio::runtime::Builder: Send & Sync & Unpin);
assert_value!(tokio::runtime::EnterGuard<'_>: Send & Sync & Unpin);
Expand Down

0 comments on commit d66a3a5

Please sign in to comment.