1 //! Trivial spinlock-based implementation of `sync::Mutex`.
2 // FIXME: Perhaps use Intel TSX to avoid locking?
7 use crate::cell
::UnsafeCell
;
9 use crate::ops
::{Deref, DerefMut}
;
10 use crate::sync
::atomic
::{AtomicBool, Ordering}
;
13 pub struct SpinMutex
<T
> {
18 unsafe impl<T
: Send
> Send
for SpinMutex
<T
> {}
19 unsafe impl<T
: Send
> Sync
for SpinMutex
<T
> {}
21 pub struct SpinMutexGuard
<'a
, T
: 'a
> {
22 mutex
: &'a SpinMutex
<T
>,
25 impl<'a
, T
> !Send
for SpinMutexGuard
<'a
, T
> {}
26 unsafe impl<'a
, T
: Sync
> Sync
for SpinMutexGuard
<'a
, T
> {}
28 impl<T
> SpinMutex
<T
> {
29 pub const fn new(value
: T
) -> Self {
30 SpinMutex { value: UnsafeCell::new(value), lock: AtomicBool::new(false) }
34 pub fn lock(&self) -> SpinMutexGuard
<'_
, T
> {
36 match self.try_lock() {
38 while self.lock
.load(Ordering
::Relaxed
) {
42 Some(guard
) => return guard
,
48 pub fn try_lock(&self) -> Option
<SpinMutexGuard
<'_
, T
>> {
49 if self.lock
.compare_exchange(false, true, Ordering
::Acquire
, Ordering
::Acquire
).is_ok() {
50 Some(SpinMutexGuard { mutex: self }
)
57 /// Lock the Mutex or return false.
58 pub macro try_lock_or_false($e
:expr
) {
59 if let Some(v
) = $e
.try_lock() { v }
else { return false }
62 impl<'a
, T
> Deref
for SpinMutexGuard
<'a
, T
> {
65 fn deref(&self) -> &T
{
66 unsafe { &*self.mutex.value.get() }
70 impl<'a
, T
> DerefMut
for SpinMutexGuard
<'a
, T
> {
71 fn deref_mut(&mut self) -> &mut T
{
72 unsafe { &mut *self.mutex.value.get() }
76 impl<'a
, T
> Drop
for SpinMutexGuard
<'a
, T
> {
78 self.mutex
.lock
.store(false, Ordering
::Release
)