use std::mem::ManuallyDrop;
use crate::ring::{Completion, RingId};
pub struct Token<T: Send + 'static> {
id: usize,
ring_id: RingId,
value: ManuallyDrop<T>,
}
impl<T: Send + 'static> Token<T> {
pub(crate) fn new(ring: &mut crate::IoRing, value: T) -> std::io::Result<Self> {
let id = ring.reserve_user_data()?;
Ok(Self {
id,
ring_id: ring.ring_id(),
value: ManuallyDrop::new(value),
})
}
#[must_use]
pub fn id(&self) -> usize {
self.id
}
pub(crate) fn claim(mut self) -> T {
unsafe { ManuallyDrop::take(&mut self.value) }
}
pub fn claim_if(self, completion: &Completion) -> Result<T, Self> {
if self.id == completion.user_data() && self.ring_id == completion.ring_id() {
Ok(self.claim())
} else {
Err(self)
}
}
}
impl<T: Send + 'static> Drop for Token<T> {
fn drop(&mut self) {
}
}
impl<T: Send + 'static> std::fmt::Debug for Token<T> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("Token")
.field("id", &self.id)
.finish_non_exhaustive()
}
}
#[cfg(test)]
mod tests;