You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
87 lines
2.0 KiB
87 lines
2.0 KiB
//! Keeping state
|
|
use super::*;
|
|
use tokio::{
|
|
sync::{
|
|
Semaphore,
|
|
SemaphorePermit,
|
|
RwLock,
|
|
RwLockReadGuard,
|
|
RwLockWriteGuard,
|
|
},
|
|
};
|
|
use futures::{
|
|
future::OptionFuture,
|
|
};
|
|
|
|
use progress::logging::Logger;
|
|
|
|
/// Contains state for a set of operations
|
|
#[derive(Debug)]
|
|
pub struct State
|
|
{
|
|
cfg: config::Config,
|
|
mtx: Option<Semaphore>,
|
|
stop: RwLock<()>,
|
|
|
|
logger: Logger,
|
|
}
|
|
|
|
/// Guard for operations inside state
|
|
#[derive(Debug)]
|
|
pub struct Permit<'a>(RwLockReadGuard<'a, ()>, Option<SemaphorePermit<'a>>);
|
|
|
|
impl State
|
|
{
|
|
/// Get the logger object for this state
|
|
pub fn logger(&self) -> &Logger
|
|
{
|
|
&self.logger
|
|
}
|
|
|
|
/// Clone the logger into a new mutable one
|
|
pub fn logger_output(&self) -> Logger
|
|
{
|
|
self.logger.clone() //TODO: Eeeehhhhh this is really inefficient
|
|
}
|
|
|
|
/// A reference to the progress counter
|
|
pub fn progress(&self) -> &progress::Handle
|
|
{
|
|
self.logger.progress()
|
|
}
|
|
|
|
/// Create a new state
|
|
pub fn new(cfg: config::Config, logger: progress::logging::Logger) -> Self
|
|
{
|
|
Self {
|
|
mtx: cfg.limit.map(|x| Semaphore::new(x.into())),
|
|
cfg,
|
|
stop: RwLock::new(()),
|
|
logger,
|
|
}
|
|
}
|
|
|
|
/// Acquire exclusive lock, preventing other tasks from acquiring through either `lock` or `lockout`.
|
|
///
|
|
/// This function will yield until all other `lock` or `lockout` guards currently acquired (if any) are released.
|
|
pub async fn lockout(&self) -> RwLockWriteGuard<'_, ()>
|
|
{
|
|
self.stop.write().await
|
|
}
|
|
|
|
/// Acquire a permit for concurrent work, yielding the task if needed.
|
|
///
|
|
/// If there are currently `config().limit` premits acquired, this will yield until at least one if released.
|
|
/// If there is a `lockout` guard acquired, this will yield until it is released too.
|
|
pub async fn lock(&self) -> Permit<'_>
|
|
{
|
|
Permit(self.stop.read().await, OptionFuture::from(self.mtx.as_ref().map(Semaphore::acquire)).await)
|
|
}
|
|
|
|
/// The config object
|
|
#[inline] pub fn config(&self) -> &config::Config
|
|
{
|
|
&self.cfg
|
|
}
|
|
}
|