use bevy_ecs::prelude::{Entity, World};
use tokio::sync::mpsc::UnboundedSender as TokioSender;
use std::sync::Arc;
use crate::{BufferKeyBuilder, ChannelItem, Disposal, OperationRoster, emit_disposal};
#[derive(Clone)]
pub struct BufferAccessLifecycle {
scope: Entity,
accessor: Entity,
session: Entity,
buffer: Entity,
sender: TokioSender<ChannelItem>,
pub(crate) tracker: Arc<()>,
}
impl BufferAccessLifecycle {
pub(crate) fn new(
scope: Entity,
buffer: Entity,
session: Entity,
accessor: Entity,
sender: TokioSender<ChannelItem>,
tracker: Arc<()>,
) -> Self {
Self {
scope,
accessor,
session,
buffer,
sender,
tracker,
}
}
pub(crate) fn is_in_use(&self) -> bool {
Arc::strong_count(&self.tracker) > 1
}
}
impl Drop for BufferAccessLifecycle {
fn drop(&mut self) {
if self.is_in_use() {
let scope = self.scope;
let accessor = self.accessor;
let session = self.session;
let buffer = self.buffer;
if let Err(err) = self.sender.send(Box::new(
move |world: &mut World, roster: &mut OperationRoster| {
let disposal = Disposal::buffer_key(accessor, buffer);
emit_disposal(accessor, session, disposal, world, roster);
},
)) {
eprintln!(
"Failed to send disposal notice for dropped buffer key in \
scope [{:?}] for session [{:?}]: {}",
scope, session, err,
);
}
}
}
}
pub trait BufferKeyLifecycle {
type TargetBuffer;
fn create_key(buffer: &Self::TargetBuffer, builder: &BufferKeyBuilder) -> Self;
fn is_in_use(&self) -> bool;
fn deep_clone(&self) -> Self;
}