1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
//! Simple waiter trait for synchronous actions.
//!
//! The `Waiter` thread represents some action that can be polled for, and
//! that can also fail.
use std::thread::sleep;
use std::time::{Duration, Instant};
/// Trait representing a waiter for some asynchronous action to finish.
///
/// The type `T` is the final type of the action, `E` is an error.
pub trait Waiter<T, E> {
/// Default timeout for this action.
///
/// This timeout is used in the `wait` method.
/// If `None, wait forever by default.
fn default_wait_timeout(&self) -> Option<Duration>;
/// Default delay between two retries.
fn default_delay(&self) -> Duration;
/// Update the current state of the action.
///
/// Returns `T` if the action is finished, `None` if it is not. All errors
/// are propagated via the `Result`.
///
/// This method should not be called again after it returned the final
/// result.
fn poll(&mut self) -> Result<Option<T>, E>;
/// Error to return on timeout.
fn timeout_error(&self) -> E;
/// Wait for the default amount of time.
///
/// Consumes the `Waiter`.
/// Returns `OperationTimedOut` if the timeout is reached.
fn wait(self) -> Result<T, E>
where
Self: Sized,
{
match self.default_wait_timeout() {
Some(duration) => self.wait_for(duration),
None => self.wait_forever(),
}
}
/// Wait for specified amount of time.
///
/// Returns `OperationTimedOut` if the timeout is reached.
fn wait_for(self, duration: Duration) -> Result<T, E>
where
Self: Sized,
{
let delay = self.default_delay();
self.wait_for_with_delay(duration, delay)
}
/// Wait for specified amount of time.
fn wait_for_with_delay(mut self, duration: Duration, delay: Duration) -> Result<T, E>
where
Self: Sized,
{
let start = Instant::now();
while Instant::now().duration_since(start) <= duration {
if let Some(result) = self.poll()? {
return Ok(result);
};
sleep(delay);
}
Err(self.timeout_error())
}
/// Wait forever.
fn wait_forever(self) -> Result<T, E>
where
Self: Sized,
{
let delay = self.default_delay();
self.wait_forever_with_delay(delay)
}
/// Wait forever with given delay between attempts.
fn wait_forever_with_delay(mut self, delay: Duration) -> Result<T, E>
where
Self: Sized,
{
loop {
if let Some(result) = self.poll()? {
return Ok(result);
};
sleep(delay);
}
}
}
/// Current state of the waiter.
///
/// Type `T` is the current state of the resource, and does not have to match
/// type `T` of `Waiter<T>`.
pub trait WaiterCurrentState<T> {
/// Get the current representation of the resource.
///
/// Valid as of the last `poll` call.
fn waiter_current_state(&self) -> &T;
}