1 use core
::sync
::atomic
::{self, AtomicUsize, Ordering}
;
5 /// A simple stamped lock.
7 /// The current state of the lock.
9 /// All bits except the least significant one hold the current stamp. When locked, the state
10 /// equals 1 and doesn't contain a valid stamp.
15 pub const INIT
: Self = Self {
16 state
: AtomicUsize
::new(0),
19 /// If not locked, returns the current stamp.
21 /// This method should be called before optimistic reads.
23 pub fn optimistic_read(&self) -> Option
<usize> {
24 let state
= self.state
.load(Ordering
::Acquire
);
32 /// Returns `true` if the current stamp is equal to `stamp`.
34 /// This method should be called after optimistic reads to check whether they are valid. The
35 /// argument `stamp` should correspond to the one returned by method `optimistic_read`.
37 pub fn validate_read(&self, stamp
: usize) -> bool
{
38 atomic
::fence(Ordering
::Acquire
);
39 self.state
.load(Ordering
::Relaxed
) == stamp
42 /// Grabs the lock for writing.
44 pub fn write(&'
static self) -> SeqLockWriteGuard
{
45 let backoff
= Backoff
::new();
47 let previous
= self.state
.swap(1, Ordering
::Acquire
);
50 atomic
::fence(Ordering
::Release
);
52 return SeqLockWriteGuard
{
63 /// An RAII guard that releases the lock and increments the stamp when dropped.
64 pub struct SeqLockWriteGuard
{
66 lock
: &'
static SeqLock
,
68 /// The stamp before locking.
72 impl SeqLockWriteGuard
{
73 /// Releases the lock without incrementing the stamp.
76 self.lock
.state
.store(self.state
, Ordering
::Release
);
80 impl Drop
for SeqLockWriteGuard
{
83 // Release the lock and increment the stamp.
86 .store(self.state
.wrapping_add(2), Ordering
::Release
);