#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum LockState {
Unlocked,
Biased,
Thin,
Fat,
}
#[derive(Debug, Clone)]
pub struct Monitor {
pub owner: Option<u32>,
pub count: u32,
pub waiters: Vec<u32>,
pub lock_state: LockState,
pub biased_thread: Option<u32>,
pub bias_revocations: u32,
}
impl Monitor {
pub fn new() -> Self {
Self {
owner: None,
count: 0,
waiters: Vec::new(),
lock_state: LockState::Unlocked,
biased_thread: None,
bias_revocations: 0,
}
}
pub fn enter(&mut self, thread_id: u32) -> bool {
match self.lock_state {
LockState::Unlocked => {
self.owner = Some(thread_id);
self.count = 1;
self.biased_thread = Some(thread_id);
self.lock_state = LockState::Biased;
true
}
LockState::Biased => {
if self.biased_thread == Some(thread_id) {
self.count += 1;
true
} else {
self.bias_revocations += 1;
self.biased_thread = None;
self.lock_state = LockState::Thin;
if self.owner.is_none() {
self.owner = Some(thread_id);
self.count = 1;
true
} else {
self.waiters.push(thread_id);
self.lock_state = LockState::Fat;
false
}
}
}
LockState::Thin => {
if let Some(owner) = self.owner {
if owner == thread_id {
self.count += 1;
true
} else {
self.lock_state = LockState::Fat;
self.waiters.push(thread_id);
false
}
} else {
self.owner = Some(thread_id);
self.count = 1;
true
}
}
LockState::Fat => {
if let Some(owner) = self.owner {
if owner == thread_id {
self.count += 1;
true
} else {
self.waiters.push(thread_id);
false
}
} else {
self.owner = Some(thread_id);
self.count = 1;
true
}
}
}
}
pub fn exit(&mut self, thread_id: u32) -> bool {
if let Some(owner) = self.owner {
if owner == thread_id {
self.count -= 1;
if self.count == 0 {
self.owner = None;
if self.waiters.is_empty() {
if self.lock_state == LockState::Thin {
self.lock_state = LockState::Unlocked;
} else if self.lock_state == LockState::Biased {
self.count = 0;
} else {
self.lock_state = LockState::Unlocked;
}
} else if let Some(next_thread) = self.waiters.first() {
let next_thread = *next_thread;
self.waiters.remove(0);
self.owner = Some(next_thread);
self.count = 1;
}
}
true
} else {
false
}
} else {
false
}
}
pub fn is_owned_by(&self, thread_id: u32) -> bool {
self.owner.map_or(false, |owner| owner == thread_id)
}
pub fn is_biased_toward(&self, thread_id: u32) -> bool {
self.lock_state == LockState::Biased && self.biased_thread == Some(thread_id)
}
pub fn revoke_bias(&mut self) {
if self.lock_state == LockState::Biased {
self.biased_thread = None;
self.bias_revocations += 1;
self.lock_state = if self.owner.is_some() {
LockState::Thin
} else {
LockState::Unlocked
};
}
}
pub fn lock_stats(&self) -> MonitorStats {
MonitorStats {
lock_state: self.lock_state,
bias_revocations: self.bias_revocations,
waiter_count: self.waiters.len(),
recursion_depth: self.count,
}
}
pub fn wait(&mut self, thread_id: u32) -> bool {
if let Some(owner) = self.owner {
if owner == thread_id {
self.waiters.push(thread_id);
let old_count = self.count;
self.owner = None;
self.count = 0;
if let Some(next_thread) = self.waiters.first() {
let next_thread = *next_thread;
self.waiters.remove(0);
self.owner = Some(next_thread);
self.count = 1;
}
old_count > 0
} else {
false
}
} else {
false
}
}
pub fn notify(&mut self) -> bool {
if self.waiters.is_empty() {
false
} else {
if let Some(waiter) = self.waiters.first() {
let waiter = *waiter;
self.waiters.remove(0);
self.waiters.push(waiter);
true
} else {
false
}
}
}
pub fn notify_all(&mut self) -> usize {
let count = self.waiters.len();
if count > 0 {
self.waiters.rotate_right(1);
}
count
}
}
impl Default for Monitor {
fn default() -> Self {
Self::new()
}
}
#[derive(Debug, Clone, Copy)]
pub struct MonitorStats {
pub lock_state: LockState,
pub bias_revocations: u32,
pub waiter_count: usize,
pub recursion_depth: u32,
}