mirror of
https://github.com/tokio-rs/tokio.git
synced 2026-08-20 00:00:08 +02:00
sync: require that an RwLock has max_readers != 0 (#8076)
This commit is contained in:
@@ -266,12 +266,13 @@ impl<T: ?Sized> RwLock<T> {
|
||||
///
|
||||
/// # Panics
|
||||
///
|
||||
/// Panics if `max_reads` is more than `u32::MAX >> 3`.
|
||||
/// Panics if `max_reads` is `0` or is bigger than `u32::MAX >> 3`.
|
||||
#[track_caller]
|
||||
pub fn with_max_readers(value: T, max_reads: u32) -> RwLock<T>
|
||||
where
|
||||
T: Sized,
|
||||
{
|
||||
assert_ne!(max_reads, 0, "a RwLock may not be created with 0 readers");
|
||||
assert!(
|
||||
max_reads <= MAX_READS,
|
||||
"a RwLock may not be created with more than {MAX_READS} readers"
|
||||
@@ -367,11 +368,16 @@ impl<T: ?Sized> RwLock<T> {
|
||||
///
|
||||
/// static LOCK: RwLock<i32> = RwLock::const_with_max_readers(5, 1024);
|
||||
/// ```
|
||||
///
|
||||
/// # Panics
|
||||
///
|
||||
/// Panics if `max_reads` is `0` or is bigger than `u32::MAX >> 3`.
|
||||
#[cfg(not(all(loom, test)))]
|
||||
pub const fn const_with_max_readers(value: T, max_reads: u32) -> RwLock<T>
|
||||
where
|
||||
T: Sized,
|
||||
{
|
||||
assert!(max_reads != 0, "a RwLock may not be created with 0 readers");
|
||||
assert!(max_reads <= MAX_READS);
|
||||
|
||||
RwLock {
|
||||
@@ -771,6 +777,7 @@ impl<T: ?Sized> RwLock<T> {
|
||||
/// ```
|
||||
pub async fn write(&self) -> RwLockWriteGuard<'_, T> {
|
||||
let acquire_fut = async {
|
||||
debug_assert_ne!(self.mr, 0);
|
||||
self.s.acquire(self.mr as usize).await.unwrap_or_else(|_| {
|
||||
// The semaphore was closed. but, we never explicitly close it, and we have a
|
||||
// handle to it through the Arc, which means that this can never happen.
|
||||
@@ -906,6 +913,7 @@ impl<T: ?Sized> RwLock<T> {
|
||||
let resource_span = self.resource_span.clone();
|
||||
|
||||
let acquire_fut = async {
|
||||
debug_assert_ne!(self.mr, 0);
|
||||
self.s.acquire(self.mr as usize).await.unwrap_or_else(|_| {
|
||||
// The semaphore was closed. but, we never explicitly close it, and we have a
|
||||
// handle to it through the Arc, which means that this can never happen.
|
||||
@@ -970,6 +978,7 @@ impl<T: ?Sized> RwLock<T> {
|
||||
/// }
|
||||
/// ```
|
||||
pub fn try_write(&self) -> Result<RwLockWriteGuard<'_, T>, TryLockError> {
|
||||
debug_assert_ne!(self.mr, 0);
|
||||
match self.s.try_acquire(self.mr as usize) {
|
||||
Ok(permit) => permit,
|
||||
Err(TryAcquireError::NoPermits) => return Err(TryLockError(())),
|
||||
@@ -1028,6 +1037,7 @@ impl<T: ?Sized> RwLock<T> {
|
||||
/// }
|
||||
/// ```
|
||||
pub fn try_write_owned(self: Arc<Self>) -> Result<OwnedRwLockWriteGuard<T>, TryLockError> {
|
||||
debug_assert_ne!(self.mr, 0);
|
||||
match self.s.try_acquire(self.mr as usize) {
|
||||
Ok(permit) => permit,
|
||||
Err(TryAcquireError::NoPermits) => return Err(TryLockError(())),
|
||||
|
||||
@@ -78,6 +78,18 @@ fn exhaust_reading() {
|
||||
let _g1 = assert_ready!(t1.poll());
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[should_panic(expected = "a RwLock may not be created with 0 readers")]
|
||||
fn zero_max_readers() {
|
||||
RwLock::with_max_readers(100, 0);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[should_panic(expected = "a RwLock may not be created with 0 readers")]
|
||||
fn zero_max_readers_const() {
|
||||
RwLock::const_with_max_readers(100, 0);
|
||||
}
|
||||
|
||||
// When there is an active exclusive owner, subsequent exclusive access should not be possible
|
||||
#[test]
|
||||
fn write_exclusive_pending() {
|
||||
|
||||
Reference in New Issue
Block a user