future_clicker/
completer.rs1use std::{mem, sync::Arc};
2
3use parking_lot::Mutex;
4use tracing::{instrument, trace};
5
6use crate::{state::State, Error, Result};
7
8#[derive(Debug)]
13#[allow(clippy::module_name_repetitions)]
14pub struct FutureClicker<T: Unpin + Send + 'static> {
15 pub(crate) state: Arc<Mutex<State<T>>>,
16}
17
18impl<T: Unpin + Send + 'static> FutureClicker<T> {
19 #[instrument(skip_all)]
25 pub fn complete(self, value: T) -> Result<()> {
26 use State::{Complete, Dropped, Incomplete, Waiting};
27
28 trace!("complete");
29
30 let mut state = self.state.lock_arc();
31
32 trace!("have lock");
33
34 match mem::replace(&mut *state, State::Complete(Some(value))) {
35 Incomplete => Ok(()),
36 Waiting(waker) => {
37 waker.wake();
38 Ok(())
39 }
40 old @ Complete(_) => {
41 *state = old;
42 Err(Error::AlreadyCompleted)
43 }
44 old @ Dropped => {
45 *state = old;
46 Err(Error::CompleterDropped)
47 }
48 }
49 }
50}
51
52impl<T: Unpin + Send + 'static> Drop for FutureClicker<T> {
53 #[instrument(skip_all)]
54 fn drop(&mut self) {
55 use State::{Complete, Dropped, Incomplete, Waiting};
56 trace!("Drop");
57 let mut state = self.state.lock_arc();
58 trace!("Locked");
59
60 match mem::replace(&mut *state, Dropped) {
61 Incomplete | Dropped => {}
62 Waiting(waker) => waker.wake(),
63 old @ Complete(_) => *state = old,
64 }
65 }
66}