#![allow(dead_code)]
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct AtomicCounter {
value: u64,
}
impl AtomicCounter {
#[must_use]
pub fn new(v: u64) -> Self {
Self { value: v }
}
pub fn increment(&mut self) -> u64 {
self.value = self.value.saturating_add(1);
self.value
}
pub fn decrement(&mut self) -> u64 {
self.value = self.value.saturating_sub(1);
self.value
}
#[must_use]
pub fn get(&self) -> u64 {
self.value
}
pub fn set(&mut self, v: u64) {
self.value = v;
}
}
impl Default for AtomicCounter {
fn default() -> Self {
Self::new(0)
}
}
#[derive(Debug, Clone)]
pub struct Semaphore {
count: i64,
max: i64,
}
impl Semaphore {
#[must_use]
pub fn new(max: i64) -> Self {
Self { count: max, max }
}
pub fn acquire(&mut self) -> bool {
if self.count > 0 {
self.count -= 1;
true
} else {
false
}
}
pub fn release(&mut self) -> bool {
if self.count < self.max {
self.count += 1;
true
} else {
false
}
}
#[must_use]
pub fn available(&self) -> i64 {
self.count
}
#[must_use]
pub fn max(&self) -> i64 {
self.max
}
}
#[derive(Debug)]
pub struct SimRwLock<T> {
data: T,
readers: u32,
writer: bool,
}
impl<T> SimRwLock<T> {
#[must_use]
pub fn new(data: T) -> Self {
Self {
data,
readers: 0,
writer: false,
}
}
pub fn read(&mut self) -> Option<&T> {
if self.writer {
return None;
}
self.readers += 1;
Some(&self.data)
}
pub fn release_read(&mut self) {
if self.readers > 0 {
self.readers -= 1;
}
}
pub fn write(&mut self) -> Option<&mut T> {
if self.writer || self.readers > 0 {
return None;
}
self.writer = true;
Some(&mut self.data)
}
pub fn try_write(&mut self) -> Option<&mut T> {
self.write()
}
pub fn release_write(&mut self) {
self.writer = false;
}
#[must_use]
pub fn reader_count(&self) -> u32 {
self.readers
}
#[must_use]
pub fn is_writing(&self) -> bool {
self.writer
}
}
#[derive(Debug, Clone)]
pub struct Barrier {
count: usize,
waiting: usize,
}
impl Barrier {
#[must_use]
pub fn new(count: usize) -> Self {
Self { count, waiting: 0 }
}
pub fn wait(&mut self) -> bool {
self.waiting += 1;
if self.waiting >= self.count {
self.reset();
true
} else {
false
}
}
pub fn reset(&mut self) {
self.waiting = 0;
}
#[must_use]
pub fn waiting_count(&self) -> usize {
self.waiting
}
#[must_use]
pub fn target_count(&self) -> usize {
self.count
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_counter_increment() {
let mut c = AtomicCounter::new(0);
assert_eq!(c.increment(), 1);
assert_eq!(c.increment(), 2);
}
#[test]
fn test_counter_decrement() {
let mut c = AtomicCounter::new(5);
assert_eq!(c.decrement(), 4);
assert_eq!(c.decrement(), 3);
}
#[test]
fn test_counter_decrement_saturates() {
let mut c = AtomicCounter::new(0);
assert_eq!(c.decrement(), 0);
}
#[test]
fn test_counter_get_set() {
let mut c = AtomicCounter::new(10);
assert_eq!(c.get(), 10);
c.set(42);
assert_eq!(c.get(), 42);
}
#[test]
fn test_semaphore_acquire_release() {
let mut sem = Semaphore::new(3);
assert_eq!(sem.available(), 3);
assert!(sem.acquire());
assert_eq!(sem.available(), 2);
assert!(sem.release());
assert_eq!(sem.available(), 3);
}
#[test]
fn test_semaphore_exhausted() {
let mut sem = Semaphore::new(1);
assert!(sem.acquire());
assert!(!sem.acquire()); }
#[test]
fn test_semaphore_release_at_max() {
let mut sem = Semaphore::new(2);
assert!(!sem.release()); assert_eq!(sem.available(), 2);
}
#[test]
fn test_semaphore_max() {
let sem = Semaphore::new(5);
assert_eq!(sem.max(), 5);
}
#[test]
fn test_rwlock_read_success() {
let mut lock = SimRwLock::new(42u32);
let val = lock.read().copied();
assert_eq!(val, Some(42));
assert_eq!(lock.reader_count(), 1);
lock.release_read();
assert_eq!(lock.reader_count(), 0);
}
#[test]
fn test_rwlock_write_blocked_by_readers() {
let mut lock = SimRwLock::new(0u32);
let _ = lock.read();
assert!(lock.write().is_none());
lock.release_read();
assert!(lock.write().is_some());
}
#[test]
fn test_rwlock_read_blocked_by_writer() {
let mut lock = SimRwLock::new(0u32);
let _ = lock.write();
assert!(lock.read().is_none());
lock.release_write();
assert!(lock.read().is_some());
}
#[test]
fn test_rwlock_try_write() {
let mut lock = SimRwLock::new(99u32);
{
let w = lock.try_write().expect("try_write should succeed");
*w = 100;
}
lock.release_write();
let v = lock.read().copied();
assert_eq!(v, Some(100));
}
#[test]
fn test_barrier_fires() {
let mut b = Barrier::new(3);
assert!(!b.wait()); assert!(!b.wait()); assert!(b.wait()); assert_eq!(b.waiting_count(), 0);
}
#[test]
fn test_barrier_cyclic() {
let mut b = Barrier::new(2);
assert!(!b.wait());
assert!(b.wait()); assert!(!b.wait());
assert!(b.wait()); }
#[test]
fn test_barrier_target_count() {
let b = Barrier::new(7);
assert_eq!(b.target_count(), 7);
}
}