minor doc fixes and edge case handling

This commit is contained in:
Daniella / Tove 2024-07-14 02:03:03 +00:00
parent 131bc549d2
commit a7a57b23f7
5 changed files with 33 additions and 7 deletions

View file

@ -3,7 +3,7 @@ name = "microlock"
description = "A crate for waiting: Small locks and other timing things!"
license = "MIT"
repository = "https://git.tudbut.de/tudbut/microlock"
version = "0.2.0"
version = "0.2.1"
edition = "2021"
[dependencies]

View file

@ -11,8 +11,8 @@ pub trait Lock {
/// Locks the lock indefinitely. In case of a timed one, the previous
/// target will be replaced without releasing the waiting threads.
fn lock(&self);
/// Locks the lock indefinitely like [`lock`], UNLESS unlock was called
/// more than once. If someone tried to unlock the lock while it was
/// Locks the lock indefinitely like [`Lock::lock`], UNLESS unlock was
/// called more than once. If someone tried to unlock the lock while it was
/// already unlocked, this will NOT lock it. Returns false and resets
/// the double-unlock check if the locking failed.
fn try_lock(&self) -> bool;

View file

@ -15,7 +15,7 @@ struct TimedLockData {
remain_locked: bool,
}
/// An untimed lock. This can be locked and unlocked, and it will unlock on
/// A timed lock. This can be locked and unlocked, and it will unlock on
/// its own after a timeout, if specified (see [`UntimedLock`] for a
/// non-expiring lock). If a thread calls wait_here on a locked lock, it will
/// wait until the lock is unlocked by another thread, or the lock expires.

View file

@ -3,16 +3,31 @@ use std::{
time::{Duration, Instant},
};
/// Our real representation of an Infinite duration.
pub const INFINITE_DURATION: Duration = Duration::new(u64::MAX, 1_000_000_000 - 1);
#[derive(Clone, Copy, PartialEq, Eq)]
/// A duration wrapper supporting elapsed/negative, real, and infinite
/// durations. Due to the solar system's impending collapse before the 64 bit
/// integer limit of seconds is reached, an Infinite duration is translated
/// to that when turning this back info a normal duration. If you run your
/// program for longer than the sun's entire lifespan including the past, this
/// may cause an issue. But I think you'll have much bigger issues long before
/// that, including the fact that you even came up with that idea.
pub enum TimerDuration {
Elapsed,
Real(Duration),
Infinite,
}
impl TimerDuration {
/// Takes the difference between a TimerDuration a and a Duration b,
/// resulting in either a negative (Elapsed) duration or a Real one.
/// The Infinite duration is passed through as-is, with no subtraction
/// done to it.
pub fn from_difference(a: TimerDuration, b: Duration) -> TimerDuration {
if a == TimerDuration::Infinite {
return a;
}
let a = a.to_real();
if a < b {
TimerDuration::Elapsed
@ -21,6 +36,8 @@ impl TimerDuration {
}
}
/// Converts this into a Duration that is waitable by rust's standard
/// functions, for use in e.g. specifying timeouts to std operations.
pub fn to_real(&self) -> Duration {
match *self {
Self::Real(d) if d > Duration::ZERO => d,
@ -34,6 +51,9 @@ impl From<Duration> for TimerDuration {
if value == Duration::ZERO {
return Self::Elapsed;
}
if value == INFINITE_DURATION {
return Self::Infinite;
}
Self::Real(value)
}
}
@ -57,6 +77,8 @@ impl Ord for TimerDuration {
}
#[derive(Clone, Copy)]
/// Holds a start time and a TimerDuration and allows for the time elapsed
/// and the time left to be queried. Timers are immutable.
pub struct Timer(Instant, TimerDuration);
impl Timer {
pub fn new(d: TimerDuration) -> Self {
@ -68,8 +90,12 @@ impl Timer {
}
}
/// Something with a timeout.
pub trait Timed {
/// Returns if the time has elapsed or not.
fn has_elapsed(&self) -> bool;
/// Returns how much time is left. Unbounded and elapsed durations use
/// Infinite and Elapsed respectively. Others always return Real.
fn time_left(&self) -> TimerDuration;
}
impl Timed for Timer {

View file

@ -9,9 +9,9 @@ use crate::{
};
/// An untimed lock. This can be locked and unlocked, but it will never unlock
/// on its own (see [`TimedLock`] for an expiring lock). If a thread calls
/// wait_here on a locked lock, it will wait until the lock is unlocked by
/// another thread.
/// on its own (see [`crate::TimedLock`] for an expiring lock). If a thread
/// calls wait_here on a locked lock, it will wait until the lock is unlocked
/// by another thread.
pub struct UntimedLock {
locked: Mutex<bool>,
double_unlock: Mutex<bool>,