From a7a57b23f7ab40a28c59937ffd8a11403cfc174b Mon Sep 17 00:00:00 2001 From: TudbuT Date: Sun, 14 Jul 2024 02:03:03 +0000 Subject: [PATCH] minor doc fixes and edge case handling --- Cargo.toml | 2 +- src/lib.rs | 4 ++-- src/timed.rs | 2 +- src/timer.rs | 26 ++++++++++++++++++++++++++ src/untimed.rs | 6 +++--- 5 files changed, 33 insertions(+), 7 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 2a66944..fcfde8c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -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] diff --git a/src/lib.rs b/src/lib.rs index c5374c4..5438f20 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -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; diff --git a/src/timed.rs b/src/timed.rs index afee051..9341e05 100644 --- a/src/timed.rs +++ b/src/timed.rs @@ -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. diff --git a/src/timer.rs b/src/timer.rs index a6ae3ff..f6a0526 100644 --- a/src/timer.rs +++ b/src/timer.rs @@ -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 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 { diff --git a/src/untimed.rs b/src/untimed.rs index 7decc11..c7bf16f 100644 --- a/src/untimed.rs +++ b/src/untimed.rs @@ -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, double_unlock: Mutex,