use std::sync::atomic::{AtomicIsize, Ordering};
use crate::version::Version;
#[derive(Debug)]
pub struct VersionedLock {
local_version: AtomicIsize,
}
impl VersionedLock {
pub fn new() -> VersionedLock {
VersionedLock {
local_version: AtomicIsize::new(1)
}
}
pub fn version(&self) -> Version {
self.local_version.load(Ordering::SeqCst).into()
}
pub fn try_lock(&self) -> Option<Guard<'_>> {
let current_version = self.version();
let current_version_isize = current_version.into();
if current_version.is_locked() {
return None;
}
let result = self.local_version.compare_exchange(
current_version_isize,
-current_version_isize,
Ordering::SeqCst,
Ordering::SeqCst,
);
match result {
Ok(_) => Some(Guard {
version: &self.local_version,
new_local_version: current_version,
}),
Err(_) => None,
}
}
}
pub struct Guard<'lock> {
version: &'lock AtomicIsize,
new_local_version: Version,
}
impl<'lock> Guard<'lock> {
pub fn set_version(&mut self, write_version: Version) {
self.new_local_version = write_version;
}
}
impl<'lock> Drop for Guard<'lock> {
fn drop(&mut self) {
self.version
.store(self.new_local_version.into(), Ordering::SeqCst);
}
}