Skip to content

Commit b1ec1ea

Browse files
committed
Move Spinlock to sync module
1 parent 98cbf7f commit b1ec1ea

File tree

4 files changed

+100
-74
lines changed

4 files changed

+100
-74
lines changed

src/rt/runtime.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,9 @@ use crossbeam_utils::thread::scope;
1212
use once_cell::unsync::OnceCell;
1313

1414
use crate::rt::Reactor;
15+
use crate::sync::Spinlock;
1516
use crate::task::Runnable;
16-
use crate::utils::{abort_on_panic, random, Spinlock};
17+
use crate::utils::{abort_on_panic, random};
1718

1819
thread_local! {
1920
/// A reference to the current machine, if the current thread runs tasks.

src/sync/mod.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -178,9 +178,11 @@ pub use std::sync::{Arc, Weak};
178178

179179
pub use mutex::{Mutex, MutexGuard};
180180
pub use rwlock::{RwLock, RwLockReadGuard, RwLockWriteGuard};
181+
pub(crate) use spin_lock::Spinlock;
181182

182183
mod mutex;
183184
mod rwlock;
185+
mod spin_lock;
184186

185187
cfg_unstable! {
186188
pub use barrier::{Barrier, BarrierWaitResult};

src/sync/spin_lock.rs

Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
use std::cell::UnsafeCell;
2+
use std::ops::{Deref, DerefMut};
3+
use std::sync::atomic::{AtomicBool, Ordering};
4+
5+
use crossbeam_utils::Backoff;
6+
7+
/// A simple spinlock.
8+
///
9+
/// ```
10+
/// # async_std::task::block_on(async {
11+
/// #
12+
/// use async_std::sync::{Arc, Spinlock};
13+
/// use async_std::task;
14+
///
15+
/// let m = Arc::new(Spinlock::new(0));
16+
/// let mut tasks = vec![];
17+
///
18+
/// for _ in 0..10 {
19+
/// let m = m.clone();
20+
/// tasks.push(task::spawn(async move {
21+
/// *m.lock() += 1;
22+
/// }));
23+
/// }
24+
///
25+
/// for t in tasks {
26+
/// t.await;
27+
/// }
28+
/// assert_eq!(*m.lock(), 10);
29+
/// #
30+
/// # })
31+
/// ```
32+
#[derive(Debug)]
33+
pub struct Spinlock<T> {
34+
flag: AtomicBool,
35+
value: UnsafeCell<T>,
36+
}
37+
38+
unsafe impl<T: Send> Send for Spinlock<T> {}
39+
unsafe impl<T: Send> Sync for Spinlock<T> {}
40+
41+
impl<T> Spinlock<T> {
42+
/// Returns a new spinlock initialized with `value`.
43+
pub const fn new(value: T) -> Spinlock<T> {
44+
Spinlock {
45+
flag: AtomicBool::new(false),
46+
value: UnsafeCell::new(value),
47+
}
48+
}
49+
50+
/// Locks the spinlock.
51+
pub fn lock(&self) -> SpinlockGuard<'_, T> {
52+
let backoff = Backoff::new();
53+
while self.flag.swap(true, Ordering::Acquire) {
54+
backoff.snooze();
55+
}
56+
SpinlockGuard { parent: self }
57+
}
58+
59+
/// Attempts to lock the spinlock.
60+
pub fn try_lock(&self) -> Option<SpinlockGuard<'_, T>> {
61+
if self.flag.swap(true, Ordering::Acquire) {
62+
None
63+
} else {
64+
Some(SpinlockGuard { parent: self })
65+
}
66+
}
67+
}
68+
69+
/// A guard holding a spinlock locked.
70+
#[derive(Debug)]
71+
pub struct SpinlockGuard<'a, T> {
72+
parent: &'a Spinlock<T>,
73+
}
74+
75+
unsafe impl<T: Send> Send for SpinlockGuard<'_, T> {}
76+
unsafe impl<T: Sync> Sync for SpinlockGuard<'_, T> {}
77+
78+
impl<'a, T> Drop for SpinlockGuard<'a, T> {
79+
fn drop(&mut self) {
80+
self.parent.flag.store(false, Ordering::Release);
81+
}
82+
}
83+
84+
impl<'a, T> Deref for SpinlockGuard<'a, T> {
85+
type Target = T;
86+
87+
fn deref(&self) -> &T {
88+
unsafe { &*self.parent.value.get() }
89+
}
90+
}
91+
92+
impl<'a, T> DerefMut for SpinlockGuard<'a, T> {
93+
fn deref_mut(&mut self) -> &mut T {
94+
unsafe { &mut *self.parent.value.get() }
95+
}
96+
}

src/utils.rs

Lines changed: 0 additions & 73 deletions
Original file line numberDiff line numberDiff line change
@@ -293,76 +293,3 @@ macro_rules! extension_trait {
293293
extension_trait!($($tail)*);
294294
};
295295
}
296-
297-
cfg_default! {
298-
use std::cell::UnsafeCell;
299-
use std::ops::{Deref, DerefMut};
300-
use std::sync::atomic::{AtomicBool, Ordering};
301-
302-
use crossbeam_utils::Backoff;
303-
304-
/// A simple spinlock.
305-
pub struct Spinlock<T> {
306-
flag: AtomicBool,
307-
value: UnsafeCell<T>,
308-
}
309-
310-
unsafe impl<T: Send> Send for Spinlock<T> {}
311-
unsafe impl<T: Send> Sync for Spinlock<T> {}
312-
313-
impl<T> Spinlock<T> {
314-
/// Returns a new spinlock initialized with `value`.
315-
pub const fn new(value: T) -> Spinlock<T> {
316-
Spinlock {
317-
flag: AtomicBool::new(false),
318-
value: UnsafeCell::new(value),
319-
}
320-
}
321-
322-
/// Locks the spinlock.
323-
pub fn lock(&self) -> SpinlockGuard<'_, T> {
324-
let backoff = Backoff::new();
325-
while self.flag.swap(true, Ordering::Acquire) {
326-
backoff.snooze();
327-
}
328-
SpinlockGuard { parent: self }
329-
}
330-
331-
/// Attempts to lock the spinlock.
332-
pub fn try_lock(&self) -> Option<SpinlockGuard<'_, T>> {
333-
if self.flag.swap(true, Ordering::Acquire) {
334-
None
335-
} else {
336-
Some(SpinlockGuard { parent: self })
337-
}
338-
}
339-
}
340-
341-
/// A guard holding a spinlock locked.
342-
pub struct SpinlockGuard<'a, T> {
343-
parent: &'a Spinlock<T>,
344-
}
345-
346-
unsafe impl<T: Send> Send for SpinlockGuard<'_, T> {}
347-
unsafe impl<T: Sync> Sync for SpinlockGuard<'_, T> {}
348-
349-
impl<'a, T> Drop for SpinlockGuard<'a, T> {
350-
fn drop(&mut self) {
351-
self.parent.flag.store(false, Ordering::Release);
352-
}
353-
}
354-
355-
impl<'a, T> Deref for SpinlockGuard<'a, T> {
356-
type Target = T;
357-
358-
fn deref(&self) -> &T {
359-
unsafe { &*self.parent.value.get() }
360-
}
361-
}
362-
363-
impl<'a, T> DerefMut for SpinlockGuard<'a, T> {
364-
fn deref_mut(&mut self) -> &mut T {
365-
unsafe { &mut *self.parent.value.get() }
366-
}
367-
}
368-
}

0 commit comments

Comments
 (0)