Skip to content

Commit 78b7ac3

Browse files
bors[bot]taiki-e
andauthored
Merge #835
835: channel: Replace Spinlock with Mutex r=ibraheemdev a=taiki-e Addresses one of `@thomcc's` reviews in rust-lang/rust#93563 (comment) (sorry for the late response!) Historically, the use of spinlock was introduced when the dependency on parking_lot was removed (5208895). However, given that it is used in Waker, which includes vectors that may be reallocated, using mutex seems to be the right choice here. r? `@ibraheemdev` bors d=ibraheemdev Co-authored-by: Taiki Endo <[email protected]>
2 parents 80224bc + 89cf973 commit 78b7ac3

File tree

3 files changed

+44
-88
lines changed

3 files changed

+44
-88
lines changed

crossbeam-channel/src/flavors/zero.rs

+34-24
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
use std::cell::UnsafeCell;
66
use std::marker::PhantomData;
77
use std::sync::atomic::{AtomicBool, Ordering};
8+
use std::sync::Mutex;
89
use std::time::Instant;
910
use std::{fmt, ptr};
1011

@@ -13,7 +14,6 @@ use crossbeam_utils::Backoff;
1314
use crate::context::Context;
1415
use crate::err::{RecvTimeoutError, SendTimeoutError, TryRecvError, TrySendError};
1516
use crate::select::{Operation, SelectHandle, Selected, Token};
16-
use crate::utils::Spinlock;
1717
use crate::waker::Waker;
1818

1919
/// A pointer to a packet.
@@ -95,7 +95,7 @@ struct Inner {
9595
/// Zero-capacity channel.
9696
pub(crate) struct Channel<T> {
9797
/// Inner representation of the channel.
98-
inner: Spinlock<Inner>,
98+
inner: Mutex<Inner>,
9999

100100
/// Indicates that dropping a `Channel<T>` may drop values of type `T`.
101101
_marker: PhantomData<T>,
@@ -105,7 +105,7 @@ impl<T> Channel<T> {
105105
/// Constructs a new zero-capacity channel.
106106
pub(crate) fn new() -> Self {
107107
Channel {
108-
inner: Spinlock::new(Inner {
108+
inner: Mutex::new(Inner {
109109
senders: Waker::new(),
110110
receivers: Waker::new(),
111111
is_disconnected: false,
@@ -126,7 +126,7 @@ impl<T> Channel<T> {
126126

127127
/// Attempts to reserve a slot for sending a message.
128128
fn start_send(&self, token: &mut Token) -> bool {
129-
let mut inner = self.inner.lock();
129+
let mut inner = self.inner.lock().unwrap();
130130

131131
// If there's a waiting receiver, pair up with it.
132132
if let Some(operation) = inner.receivers.try_select() {
@@ -155,7 +155,7 @@ impl<T> Channel<T> {
155155

156156
/// Attempts to pair up with a sender.
157157
fn start_recv(&self, token: &mut Token) -> bool {
158-
let mut inner = self.inner.lock();
158+
let mut inner = self.inner.lock().unwrap();
159159

160160
// If there's a waiting sender, pair up with it.
161161
if let Some(operation) = inner.senders.try_select() {
@@ -198,7 +198,7 @@ impl<T> Channel<T> {
198198
/// Attempts to send a message into the channel.
199199
pub(crate) fn try_send(&self, msg: T) -> Result<(), TrySendError<T>> {
200200
let token = &mut Token::default();
201-
let mut inner = self.inner.lock();
201+
let mut inner = self.inner.lock().unwrap();
202202

203203
// If there's a waiting receiver, pair up with it.
204204
if let Some(operation) = inner.receivers.try_select() {
@@ -222,7 +222,7 @@ impl<T> Channel<T> {
222222
deadline: Option<Instant>,
223223
) -> Result<(), SendTimeoutError<T>> {
224224
let token = &mut Token::default();
225-
let mut inner = self.inner.lock();
225+
let mut inner = self.inner.lock().unwrap();
226226

227227
// If there's a waiting receiver, pair up with it.
228228
if let Some(operation) = inner.receivers.try_select() {
@@ -254,12 +254,12 @@ impl<T> Channel<T> {
254254
match sel {
255255
Selected::Waiting => unreachable!(),
256256
Selected::Aborted => {
257-
self.inner.lock().senders.unregister(oper).unwrap();
257+
self.inner.lock().unwrap().senders.unregister(oper).unwrap();
258258
let msg = unsafe { packet.msg.get().replace(None).unwrap() };
259259
Err(SendTimeoutError::Timeout(msg))
260260
}
261261
Selected::Disconnected => {
262-
self.inner.lock().senders.unregister(oper).unwrap();
262+
self.inner.lock().unwrap().senders.unregister(oper).unwrap();
263263
let msg = unsafe { packet.msg.get().replace(None).unwrap() };
264264
Err(SendTimeoutError::Disconnected(msg))
265265
}
@@ -275,7 +275,7 @@ impl<T> Channel<T> {
275275
/// Attempts to receive a message without blocking.
276276
pub(crate) fn try_recv(&self) -> Result<T, TryRecvError> {
277277
let token = &mut Token::default();
278-
let mut inner = self.inner.lock();
278+
let mut inner = self.inner.lock().unwrap();
279279

280280
// If there's a waiting sender, pair up with it.
281281
if let Some(operation) = inner.senders.try_select() {
@@ -292,7 +292,7 @@ impl<T> Channel<T> {
292292
/// Receives a message from the channel.
293293
pub(crate) fn recv(&self, deadline: Option<Instant>) -> Result<T, RecvTimeoutError> {
294294
let token = &mut Token::default();
295-
let mut inner = self.inner.lock();
295+
let mut inner = self.inner.lock().unwrap();
296296

297297
// If there's a waiting sender, pair up with it.
298298
if let Some(operation) = inner.senders.try_select() {
@@ -325,11 +325,21 @@ impl<T> Channel<T> {
325325
match sel {
326326
Selected::Waiting => unreachable!(),
327327
Selected::Aborted => {
328-
self.inner.lock().receivers.unregister(oper).unwrap();
328+
self.inner
329+
.lock()
330+
.unwrap()
331+
.receivers
332+
.unregister(oper)
333+
.unwrap();
329334
Err(RecvTimeoutError::Timeout)
330335
}
331336
Selected::Disconnected => {
332-
self.inner.lock().receivers.unregister(oper).unwrap();
337+
self.inner
338+
.lock()
339+
.unwrap()
340+
.receivers
341+
.unregister(oper)
342+
.unwrap();
333343
Err(RecvTimeoutError::Disconnected)
334344
}
335345
Selected::Operation(_) => {
@@ -345,7 +355,7 @@ impl<T> Channel<T> {
345355
///
346356
/// Returns `true` if this call disconnected the channel.
347357
pub(crate) fn disconnect(&self) -> bool {
348-
let mut inner = self.inner.lock();
358+
let mut inner = self.inner.lock().unwrap();
349359

350360
if !inner.is_disconnected {
351361
inner.is_disconnected = true;
@@ -396,7 +406,7 @@ impl<T> SelectHandle for Receiver<'_, T> {
396406
fn register(&self, oper: Operation, cx: &Context) -> bool {
397407
let packet = Box::into_raw(Packet::<T>::empty_on_heap());
398408

399-
let mut inner = self.0.inner.lock();
409+
let mut inner = self.0.inner.lock().unwrap();
400410
inner
401411
.receivers
402412
.register_with_packet(oper, packet as *mut (), cx);
@@ -405,7 +415,7 @@ impl<T> SelectHandle for Receiver<'_, T> {
405415
}
406416

407417
fn unregister(&self, oper: Operation) {
408-
if let Some(operation) = self.0.inner.lock().receivers.unregister(oper) {
418+
if let Some(operation) = self.0.inner.lock().unwrap().receivers.unregister(oper) {
409419
unsafe {
410420
drop(Box::from_raw(operation.packet as *mut Packet<T>));
411421
}
@@ -418,18 +428,18 @@ impl<T> SelectHandle for Receiver<'_, T> {
418428
}
419429

420430
fn is_ready(&self) -> bool {
421-
let inner = self.0.inner.lock();
431+
let inner = self.0.inner.lock().unwrap();
422432
inner.senders.can_select() || inner.is_disconnected
423433
}
424434

425435
fn watch(&self, oper: Operation, cx: &Context) -> bool {
426-
let mut inner = self.0.inner.lock();
436+
let mut inner = self.0.inner.lock().unwrap();
427437
inner.receivers.watch(oper, cx);
428438
inner.senders.can_select() || inner.is_disconnected
429439
}
430440

431441
fn unwatch(&self, oper: Operation) {
432-
let mut inner = self.0.inner.lock();
442+
let mut inner = self.0.inner.lock().unwrap();
433443
inner.receivers.unwatch(oper);
434444
}
435445
}
@@ -446,7 +456,7 @@ impl<T> SelectHandle for Sender<'_, T> {
446456
fn register(&self, oper: Operation, cx: &Context) -> bool {
447457
let packet = Box::into_raw(Packet::<T>::empty_on_heap());
448458

449-
let mut inner = self.0.inner.lock();
459+
let mut inner = self.0.inner.lock().unwrap();
450460
inner
451461
.senders
452462
.register_with_packet(oper, packet as *mut (), cx);
@@ -455,7 +465,7 @@ impl<T> SelectHandle for Sender<'_, T> {
455465
}
456466

457467
fn unregister(&self, oper: Operation) {
458-
if let Some(operation) = self.0.inner.lock().senders.unregister(oper) {
468+
if let Some(operation) = self.0.inner.lock().unwrap().senders.unregister(oper) {
459469
unsafe {
460470
drop(Box::from_raw(operation.packet as *mut Packet<T>));
461471
}
@@ -468,18 +478,18 @@ impl<T> SelectHandle for Sender<'_, T> {
468478
}
469479

470480
fn is_ready(&self) -> bool {
471-
let inner = self.0.inner.lock();
481+
let inner = self.0.inner.lock().unwrap();
472482
inner.receivers.can_select() || inner.is_disconnected
473483
}
474484

475485
fn watch(&self, oper: Operation, cx: &Context) -> bool {
476-
let mut inner = self.0.inner.lock();
486+
let mut inner = self.0.inner.lock().unwrap();
477487
inner.senders.watch(oper, cx);
478488
inner.receivers.can_select() || inner.is_disconnected
479489
}
480490

481491
fn unwatch(&self, oper: Operation) {
482-
let mut inner = self.0.inner.lock();
492+
let mut inner = self.0.inner.lock().unwrap();
483493
inner.senders.unwatch(oper);
484494
}
485495
}

crossbeam-channel/src/utils.rs

+1-55
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,10 @@
11
//! Miscellaneous utilities.
22
3-
use std::cell::{Cell, UnsafeCell};
3+
use std::cell::Cell;
44
use std::num::Wrapping;
5-
use std::ops::{Deref, DerefMut};
6-
use std::sync::atomic::{AtomicBool, Ordering};
75
use std::thread;
86
use std::time::{Duration, Instant};
97

10-
use crossbeam_utils::Backoff;
11-
128
/// Randomly shuffles a slice.
139
pub(crate) fn shuffle<T>(v: &mut [T]) {
1410
let len = v.len();
@@ -68,53 +64,3 @@ pub(crate) fn convert_timeout_to_deadline(timeout: Duration) -> Instant {
6864
None => Instant::now() + Duration::from_secs(86400 * 365 * 30),
6965
}
7066
}
71-
72-
/// A simple spinlock.
73-
pub(crate) struct Spinlock<T> {
74-
flag: AtomicBool,
75-
value: UnsafeCell<T>,
76-
}
77-
78-
impl<T> Spinlock<T> {
79-
/// Returns a new spinlock initialized with `value`.
80-
pub(crate) fn new(value: T) -> Spinlock<T> {
81-
Spinlock {
82-
flag: AtomicBool::new(false),
83-
value: UnsafeCell::new(value),
84-
}
85-
}
86-
87-
/// Locks the spinlock.
88-
pub(crate) fn lock(&self) -> SpinlockGuard<'_, T> {
89-
let backoff = Backoff::new();
90-
while self.flag.swap(true, Ordering::Acquire) {
91-
backoff.snooze();
92-
}
93-
SpinlockGuard { parent: self }
94-
}
95-
}
96-
97-
/// A guard holding a spinlock locked.
98-
pub(crate) struct SpinlockGuard<'a, T> {
99-
parent: &'a Spinlock<T>,
100-
}
101-
102-
impl<T> Drop for SpinlockGuard<'_, T> {
103-
fn drop(&mut self) {
104-
self.parent.flag.store(false, Ordering::Release);
105-
}
106-
}
107-
108-
impl<T> Deref for SpinlockGuard<'_, T> {
109-
type Target = T;
110-
111-
fn deref(&self) -> &T {
112-
unsafe { &*self.parent.value.get() }
113-
}
114-
}
115-
116-
impl<T> DerefMut for SpinlockGuard<'_, T> {
117-
fn deref_mut(&mut self) -> &mut T {
118-
unsafe { &mut *self.parent.value.get() }
119-
}
120-
}

crossbeam-channel/src/waker.rs

+9-9
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,11 @@
22
33
use std::ptr;
44
use std::sync::atomic::{AtomicBool, Ordering};
5+
use std::sync::Mutex;
56
use std::thread::{self, ThreadId};
67

78
use crate::context::Context;
89
use crate::select::{Operation, Selected};
9-
use crate::utils::Spinlock;
1010

1111
/// Represents a thread blocked on a specific channel operation.
1212
pub(crate) struct Entry {
@@ -176,7 +176,7 @@ impl Drop for Waker {
176176
/// This is a simple wrapper around `Waker` that internally uses a mutex for synchronization.
177177
pub(crate) struct SyncWaker {
178178
/// The inner `Waker`.
179-
inner: Spinlock<Waker>,
179+
inner: Mutex<Waker>,
180180

181181
/// `true` if the waker is empty.
182182
is_empty: AtomicBool,
@@ -187,15 +187,15 @@ impl SyncWaker {
187187
#[inline]
188188
pub(crate) fn new() -> Self {
189189
SyncWaker {
190-
inner: Spinlock::new(Waker::new()),
190+
inner: Mutex::new(Waker::new()),
191191
is_empty: AtomicBool::new(true),
192192
}
193193
}
194194

195195
/// Registers the current thread with an operation.
196196
#[inline]
197197
pub(crate) fn register(&self, oper: Operation, cx: &Context) {
198-
let mut inner = self.inner.lock();
198+
let mut inner = self.inner.lock().unwrap();
199199
inner.register(oper, cx);
200200
self.is_empty.store(
201201
inner.selectors.is_empty() && inner.observers.is_empty(),
@@ -206,7 +206,7 @@ impl SyncWaker {
206206
/// Unregisters an operation previously registered by the current thread.
207207
#[inline]
208208
pub(crate) fn unregister(&self, oper: Operation) -> Option<Entry> {
209-
let mut inner = self.inner.lock();
209+
let mut inner = self.inner.lock().unwrap();
210210
let entry = inner.unregister(oper);
211211
self.is_empty.store(
212212
inner.selectors.is_empty() && inner.observers.is_empty(),
@@ -219,7 +219,7 @@ impl SyncWaker {
219219
#[inline]
220220
pub(crate) fn notify(&self) {
221221
if !self.is_empty.load(Ordering::SeqCst) {
222-
let mut inner = self.inner.lock();
222+
let mut inner = self.inner.lock().unwrap();
223223
if !self.is_empty.load(Ordering::SeqCst) {
224224
inner.try_select();
225225
inner.notify();
@@ -234,7 +234,7 @@ impl SyncWaker {
234234
/// Registers an operation waiting to be ready.
235235
#[inline]
236236
pub(crate) fn watch(&self, oper: Operation, cx: &Context) {
237-
let mut inner = self.inner.lock();
237+
let mut inner = self.inner.lock().unwrap();
238238
inner.watch(oper, cx);
239239
self.is_empty.store(
240240
inner.selectors.is_empty() && inner.observers.is_empty(),
@@ -245,7 +245,7 @@ impl SyncWaker {
245245
/// Unregisters an operation waiting to be ready.
246246
#[inline]
247247
pub(crate) fn unwatch(&self, oper: Operation) {
248-
let mut inner = self.inner.lock();
248+
let mut inner = self.inner.lock().unwrap();
249249
inner.unwatch(oper);
250250
self.is_empty.store(
251251
inner.selectors.is_empty() && inner.observers.is_empty(),
@@ -256,7 +256,7 @@ impl SyncWaker {
256256
/// Notifies all threads that the channel is disconnected.
257257
#[inline]
258258
pub(crate) fn disconnect(&self) {
259-
let mut inner = self.inner.lock();
259+
let mut inner = self.inner.lock().unwrap();
260260
inner.disconnect();
261261
self.is_empty.store(
262262
inner.selectors.is_empty() && inner.observers.is_empty(),

0 commit comments

Comments
 (0)