minor doc fixes and edge case handling
This commit is contained in:
parent
131bc549d2
commit
a7a57b23f7
5 changed files with 33 additions and 7 deletions
|
@ -3,7 +3,7 @@ name = "microlock"
|
||||||
description = "A crate for waiting: Small locks and other timing things!"
|
description = "A crate for waiting: Small locks and other timing things!"
|
||||||
license = "MIT"
|
license = "MIT"
|
||||||
repository = "https://git.tudbut.de/tudbut/microlock"
|
repository = "https://git.tudbut.de/tudbut/microlock"
|
||||||
version = "0.2.0"
|
version = "0.2.1"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
|
|
|
@ -11,8 +11,8 @@ pub trait Lock {
|
||||||
/// Locks the lock indefinitely. In case of a timed one, the previous
|
/// Locks the lock indefinitely. In case of a timed one, the previous
|
||||||
/// target will be replaced without releasing the waiting threads.
|
/// target will be replaced without releasing the waiting threads.
|
||||||
fn lock(&self);
|
fn lock(&self);
|
||||||
/// Locks the lock indefinitely like [`lock`], UNLESS unlock was called
|
/// Locks the lock indefinitely like [`Lock::lock`], UNLESS unlock was
|
||||||
/// more than once. If someone tried to unlock the lock while it 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
|
/// already unlocked, this will NOT lock it. Returns false and resets
|
||||||
/// the double-unlock check if the locking failed.
|
/// the double-unlock check if the locking failed.
|
||||||
fn try_lock(&self) -> bool;
|
fn try_lock(&self) -> bool;
|
||||||
|
|
|
@ -15,7 +15,7 @@ struct TimedLockData {
|
||||||
remain_locked: bool,
|
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
|
/// 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
|
/// 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.
|
/// wait until the lock is unlocked by another thread, or the lock expires.
|
||||||
|
|
26
src/timer.rs
26
src/timer.rs
|
@ -3,16 +3,31 @@ use std::{
|
||||||
time::{Duration, Instant},
|
time::{Duration, Instant},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/// Our real representation of an Infinite duration.
|
||||||
pub const INFINITE_DURATION: Duration = Duration::new(u64::MAX, 1_000_000_000 - 1);
|
pub const INFINITE_DURATION: Duration = Duration::new(u64::MAX, 1_000_000_000 - 1);
|
||||||
|
|
||||||
#[derive(Clone, Copy, PartialEq, Eq)]
|
#[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 {
|
pub enum TimerDuration {
|
||||||
Elapsed,
|
Elapsed,
|
||||||
Real(Duration),
|
Real(Duration),
|
||||||
Infinite,
|
Infinite,
|
||||||
}
|
}
|
||||||
impl TimerDuration {
|
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 {
|
pub fn from_difference(a: TimerDuration, b: Duration) -> TimerDuration {
|
||||||
|
if a == TimerDuration::Infinite {
|
||||||
|
return a;
|
||||||
|
}
|
||||||
let a = a.to_real();
|
let a = a.to_real();
|
||||||
if a < b {
|
if a < b {
|
||||||
TimerDuration::Elapsed
|
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 {
|
pub fn to_real(&self) -> Duration {
|
||||||
match *self {
|
match *self {
|
||||||
Self::Real(d) if d > Duration::ZERO => d,
|
Self::Real(d) if d > Duration::ZERO => d,
|
||||||
|
@ -34,6 +51,9 @@ impl From<Duration> for TimerDuration {
|
||||||
if value == Duration::ZERO {
|
if value == Duration::ZERO {
|
||||||
return Self::Elapsed;
|
return Self::Elapsed;
|
||||||
}
|
}
|
||||||
|
if value == INFINITE_DURATION {
|
||||||
|
return Self::Infinite;
|
||||||
|
}
|
||||||
Self::Real(value)
|
Self::Real(value)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -57,6 +77,8 @@ impl Ord for TimerDuration {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Copy)]
|
#[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);
|
pub struct Timer(Instant, TimerDuration);
|
||||||
impl Timer {
|
impl Timer {
|
||||||
pub fn new(d: TimerDuration) -> Self {
|
pub fn new(d: TimerDuration) -> Self {
|
||||||
|
@ -68,8 +90,12 @@ impl Timer {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Something with a timeout.
|
||||||
pub trait Timed {
|
pub trait Timed {
|
||||||
|
/// Returns if the time has elapsed or not.
|
||||||
fn has_elapsed(&self) -> bool;
|
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;
|
fn time_left(&self) -> TimerDuration;
|
||||||
}
|
}
|
||||||
impl Timed for Timer {
|
impl Timed for Timer {
|
||||||
|
|
|
@ -9,9 +9,9 @@ use crate::{
|
||||||
};
|
};
|
||||||
|
|
||||||
/// An untimed lock. This can be locked and unlocked, but it will never unlock
|
/// 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
|
/// on its own (see [`crate::TimedLock`] for an expiring lock). If a thread
|
||||||
/// wait_here on a locked lock, it will wait until the lock is unlocked by
|
/// calls wait_here on a locked lock, it will wait until the lock is unlocked
|
||||||
/// another thread.
|
/// by another thread.
|
||||||
pub struct UntimedLock {
|
pub struct UntimedLock {
|
||||||
locked: Mutex<bool>,
|
locked: Mutex<bool>,
|
||||||
double_unlock: Mutex<bool>,
|
double_unlock: Mutex<bool>,
|
||||||
|
|
Loading…
Add table
Reference in a new issue