use serde::{Deserialize, Deserializer, Serialize, Serializer};
use std::sync::Arc;
use std::sync::atomic::{AtomicBool, Ordering};
#[cfg_attr(alef, alef(skip))]
#[derive(Debug, Clone, Default)]
pub struct CancellationToken {
cancelled: Arc<AtomicBool>,
}
impl CancellationToken {
#[cfg(test)]
pub(crate) fn new() -> Self {
Self::default()
}
#[cfg(any(all(feature = "tokio-runtime", not(target_arch = "wasm32")), test))]
#[inline]
pub(crate) fn cancel(&self) {
self.cancelled.store(true, Ordering::Relaxed);
}
#[inline]
pub(crate) fn is_cancelled(&self) -> bool {
self.cancelled.load(Ordering::Relaxed)
}
}
impl Serialize for CancellationToken {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
let state = self.is_cancelled();
state.serialize(serializer)
}
}
impl<'de> Deserialize<'de> for CancellationToken {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: Deserializer<'de>,
{
let cancelled = bool::deserialize(deserializer)?;
Ok(CancellationToken {
cancelled: Arc::new(AtomicBool::new(cancelled)),
})
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_new_token_is_not_cancelled() {
let token = CancellationToken::new();
assert!(!token.is_cancelled());
}
#[test]
fn test_cancel_sets_flag() {
let token = CancellationToken::new();
token.cancel();
assert!(token.is_cancelled());
}
#[test]
fn test_clone_shares_state() {
let token = CancellationToken::new();
let clone = token.clone();
assert!(!clone.is_cancelled());
token.cancel();
assert!(clone.is_cancelled());
}
#[test]
fn test_cancel_is_idempotent() {
let token = CancellationToken::new();
token.cancel();
token.cancel();
assert!(token.is_cancelled());
}
#[test]
fn test_default_is_not_cancelled() {
let token = CancellationToken::default();
assert!(!token.is_cancelled());
}
}