mirror of
https://github.com/tokio-rs/tokio.git
synced 2025-09-28 12:10:37 +00:00
rt: add feature flag for using parking_lot
internally (#2164)
`parking_lot` provides synchronization primitives that tend to be more efficient than the ones in `std`. However, depending on `parking_lot` pulls in a number of dependencies resulting in additional compilation time. Adding *optional* support for `parking_lot` allows the end user to opt-in when the trade offs make sense for their case.
This commit is contained in:
parent
f9ddb93604
commit
e35038ed79
@ -90,7 +90,6 @@ time = ["slab"]
|
||||
udp = ["io-driver"]
|
||||
uds = ["io-driver", "mio-uds", "libc"]
|
||||
|
||||
|
||||
[dependencies]
|
||||
tokio-macros = { version = "0.2.3", path = "../tokio-macros", optional = true }
|
||||
|
||||
@ -105,8 +104,8 @@ memchr = { version = "2.2", optional = true }
|
||||
mio = { version = "0.6.20", optional = true }
|
||||
iovec = { version = "0.1.4", optional = true }
|
||||
num_cpus = { version = "1.8.0", optional = true }
|
||||
# Backs `DelayQueue`
|
||||
slab = { version = "0.4.1", optional = true }
|
||||
parking_lot = { version = "0.10.0", optional = true } # Not in full
|
||||
slab = { version = "0.4.1", optional = true } # Backs `DelayQueue`
|
||||
|
||||
[target.'cfg(unix)'.dependencies]
|
||||
mio-uds = { version = "0.6.5", optional = true }
|
||||
|
@ -66,13 +66,13 @@
|
||||
//! is possible to just enable certain features over others. By default, Tokio
|
||||
//! does not enable any features but allows one to enable a subset for their use
|
||||
//! case. Below is a list of the available feature flags. You may also notice
|
||||
//! above each function, struct and trait there is a set of feature flags
|
||||
//! that are required for that item to be enabled. If you are new to Tokio it is
|
||||
//! recommended that you use the `full` feature flag which will enable everything.
|
||||
//! above each function, struct and trait there is listed one or more feature flags
|
||||
//! that are required for that item to be used. If you are new to Tokio it is
|
||||
//! recommended that you use the `full` feature flag which will enable all public APIs.
|
||||
//! Beware though that this will pull in many extra dependencies that you may not
|
||||
//! need.
|
||||
//!
|
||||
//! - `full`: Enables all Tokio features and every API will be available.
|
||||
//! - `full`: Enables all Tokio public API features listed below.
|
||||
//! - `rt-core`: Enables `tokio::spawn` and the basic (single-threaded) scheduler.
|
||||
//! - `rt-threaded`: Enables the heavier, multi-threaded, work-stealing scheduler.
|
||||
//! - `rt-util`: Enables non-scheduler utilities.
|
||||
@ -95,15 +95,25 @@
|
||||
//! - `test-util`: Enables testing based infrastructure for the Tokio runtime.
|
||||
//! - `blocking`: Enables `block_in_place` and `spawn_blocking`.
|
||||
//!
|
||||
//! _Note: `AsyncRead` and `AsyncWrite` do not require any features and are
|
||||
//! enabled by default._
|
||||
//! _Note: `AsyncRead` and `AsyncWrite` traits do not require any features and are
|
||||
//! always available._
|
||||
//!
|
||||
//! ### Internal features
|
||||
//!
|
||||
//! These features do not expose any new API, but influence internal
|
||||
//! implementation aspects of Tokio, and can pull in additional
|
||||
//! dependencies. They are not included in `full`:
|
||||
//!
|
||||
//! - `parking_lot`: As a potential optimization, use the _parking_lot_ crate's
|
||||
//! synchronization primitives internally. MSRV may increase according to the
|
||||
//! _parking_lot_ release in use.
|
||||
//!
|
||||
//! [feature flags]: https://doc.rust-lang.org/cargo/reference/manifest.html#the-features-section
|
||||
//!
|
||||
//! ### Authoring applications
|
||||
//!
|
||||
//! Tokio is great for writing applications and most users in this case shouldn't
|
||||
//! worry to much about what features they should pick. If you're unsure, we suggest
|
||||
//! worry too much about what features they should pick. If you're unsure, we suggest
|
||||
//! going with `full` to ensure that you don't run into any road blocks while you're
|
||||
//! building your application.
|
||||
//!
|
||||
|
@ -38,7 +38,26 @@ pub(crate) mod rand {
|
||||
}
|
||||
|
||||
pub(crate) mod sync {
|
||||
pub(crate) use std::sync::*;
|
||||
pub(crate) use std::sync::Arc;
|
||||
|
||||
#[cfg(feature = "parking_lot")]
|
||||
mod pl_wrappers;
|
||||
|
||||
// Below, make sure all the feature-influenced types are exported for
|
||||
// internal use. Note however that some are not _currently_ named by
|
||||
// consuming code.
|
||||
|
||||
#[cfg(feature = "parking_lot")]
|
||||
#[allow(unused_imports)]
|
||||
pub(crate) use pl_wrappers::{Condvar, Mutex};
|
||||
|
||||
#[cfg(feature = "parking_lot")]
|
||||
#[allow(unused_imports)]
|
||||
pub(crate) use parking_lot::{MutexGuard, WaitTimeoutResult};
|
||||
|
||||
#[cfg(not(feature = "parking_lot"))]
|
||||
#[allow(unused_imports)]
|
||||
pub(crate) use std::sync::{Condvar, Mutex, MutexGuard, WaitTimeoutResult};
|
||||
|
||||
pub(crate) mod atomic {
|
||||
pub(crate) use crate::loom::std::atomic_u32::AtomicU32;
|
||||
|
79
tokio/src/loom/std/sync/pl_wrappers.rs
Normal file
79
tokio/src/loom/std/sync/pl_wrappers.rs
Normal file
@ -0,0 +1,79 @@
|
||||
//! A minimal adaption of the `parking_lot` synchronization primitives to the
|
||||
//! equivalent `std::sync` types.
|
||||
//!
|
||||
//! This can be extended to additional types/methods as required.
|
||||
|
||||
use std::sync::{LockResult, TryLockError, TryLockResult};
|
||||
use std::time::Duration;
|
||||
|
||||
use parking_lot as pl;
|
||||
|
||||
/// Adapter for `parking_lot::Mutex` to the `std::sync::Mutex` interface.
|
||||
#[derive(Debug)]
|
||||
pub(crate) struct Mutex<T: ?Sized>(pl::Mutex<T>);
|
||||
|
||||
impl<T> Mutex<T> {
|
||||
#[inline]
|
||||
pub(crate) fn new(t: T) -> Mutex<T> {
|
||||
Mutex(pl::Mutex::new(t))
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub(crate) fn lock(&self) -> LockResult<pl::MutexGuard<'_, T>> {
|
||||
Ok(self.0.lock())
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub(crate) fn try_lock(&self) -> TryLockResult<pl::MutexGuard<'_, T>> {
|
||||
match self.0.try_lock() {
|
||||
Some(guard) => Ok(guard),
|
||||
None => Err(TryLockError::WouldBlock),
|
||||
}
|
||||
}
|
||||
|
||||
// Note: Additional methods `is_poisoned` and `into_inner`, can be
|
||||
// provided here as needed.
|
||||
}
|
||||
|
||||
/// Adapter for `parking_lot::Condvar` to the `std::sync::Condvar` interface.
|
||||
#[derive(Debug)]
|
||||
pub(crate) struct Condvar(pl::Condvar);
|
||||
|
||||
impl Condvar {
|
||||
#[inline]
|
||||
pub(crate) fn new() -> Condvar {
|
||||
Condvar(pl::Condvar::new())
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub(crate) fn notify_one(&self) {
|
||||
self.0.notify_one();
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub(crate) fn notify_all(&self) {
|
||||
self.0.notify_all();
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub(crate) fn wait<'a, T>(
|
||||
&self,
|
||||
mut guard: pl::MutexGuard<'a, T>,
|
||||
) -> LockResult<pl::MutexGuard<'a, T>> {
|
||||
self.0.wait(&mut guard);
|
||||
Ok(guard)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub(crate) fn wait_timeout<'a, T>(
|
||||
&self,
|
||||
mut guard: pl::MutexGuard<'a, T>,
|
||||
timeout: Duration,
|
||||
) -> LockResult<(pl::MutexGuard<'a, T>, pl::WaitTimeoutResult)> {
|
||||
let wtr = self.0.wait_for(&mut guard, timeout);
|
||||
Ok((guard, wtr))
|
||||
}
|
||||
|
||||
// Note: Additional methods `wait_timeout_ms`, `wait_timeout_until`,
|
||||
// `wait_until` can be provided here as needed.
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user