diff --git a/server/src/fell.rs b/server/src/fell.rs index 34b199f..61d6974 100644 --- a/server/src/fell.rs +++ b/server/src/fell.rs @@ -3,7 +3,7 @@ use std::ops::Mul; use log::{trace, warn, info}; use serde::{Serialize, Deserialize}; use time::OffsetDateTime; -use tokio::task::JoinHandle; +use tokio::task::{JoinHandle, AbortHandle}; use typetag::serde; use crate::{blocks::{Vec3, Position, Direction}, turtle::{TurtleCommander, TurtleCommand, TurtleCommandResponse, InventorySlot}, tasks::{Task, TaskState}, depot::Depots, mine::fill, paths::TRANSPARENT}; @@ -135,11 +135,11 @@ impl TreeFarm { #[serde] impl Task for TreeFarm { - fn run(&mut self,turtle:TurtleCommander) -> JoinHandle<()> { + fn run(&mut self,turtle:TurtleCommander) -> AbortHandle { let frozen = self.clone(); tokio::spawn(async move { frozen.sweep(turtle).await.unwrap(); - }) + }).abort_handle() } fn poll(&mut self) -> TaskState { diff --git a/server/src/mine.rs b/server/src/mine.rs index ee6ca8e..d17f2e6 100644 --- a/server/src/mine.rs +++ b/server/src/mine.rs @@ -1,6 +1,6 @@ use log::{info, warn}; use serde::{Serialize, Deserialize}; -use tokio::task::JoinHandle; +use tokio::task::{JoinHandle, AbortHandle}; use typetag::serde; use crate::{blocks::{Position, Vec3, Direction}, turtle::{TurtleCommand, TurtleCommander, TurtleCommandResponse, InventorySlot}, paths::TRANSPARENT, tasks::{Task, TaskState}}; @@ -188,12 +188,12 @@ impl Mine { #[serde] impl Task for Mine { - fn run(&mut self,turtle:TurtleCommander) -> JoinHandle<()> { + fn run(&mut self,turtle:TurtleCommander) -> AbortHandle { self.miners += 1; let frozen = self.clone(); tokio::spawn(async move { mine(turtle,frozen.pos, frozen.chunk).await.unwrap(); - }) + }).abort_handle() // TODO: mutability after spawn } diff --git a/server/src/tasks.rs b/server/src/tasks.rs index 96a249a..9ef3e22 100644 --- a/server/src/tasks.rs +++ b/server/src/tasks.rs @@ -1,6 +1,6 @@ -use log::info; +use log::{info, trace}; use serde::{Deserialize, Serialize}; -use tokio::task::JoinHandle; +use tokio::task::{JoinHandle, AbortHandle}; use crate::names::Name; use crate::{turtle::TurtleCommander, blocks::Position}; @@ -14,7 +14,7 @@ pub enum TaskState { #[typetag::serde(tag = "task")] pub trait Task: Send + Sync { /// Execute the task - fn run(&mut self, turtle: TurtleCommander) -> JoinHandle<()>; + fn run(&mut self, turtle: TurtleCommander) -> AbortHandle; /// Return Some if the task should be scheduled fn poll(&mut self) -> TaskState; } @@ -22,7 +22,7 @@ pub trait Task: Send + Sync { #[derive(Serialize, Deserialize)] pub struct Scheduler { #[serde(skip)] - turtles: Vec<(TurtleCommander, Option>)>, + turtles: Vec<(TurtleCommander, Option)>, tasks: Vec>, } @@ -49,7 +49,7 @@ impl Scheduler { } pub fn add_task(&mut self, task: Box) { - info!("new task"); + trace!("new task"); self.tasks.push(task); } @@ -57,12 +57,13 @@ impl Scheduler { for turtle in &mut self.turtles { if let Some(join) = &turtle.1 { if join.is_finished() { + trace!("#{} completed task", turtle.0.name().to_num()); turtle.1 = None; } } } - let mut free_turtles: Vec<&mut (TurtleCommander, Option>)> = + let mut free_turtles: Vec<&mut (TurtleCommander, Option)> = self.turtles.iter_mut().filter(|t| t.1.is_none()).collect(); let mut turtle_positions = Vec::new(); @@ -74,13 +75,16 @@ impl Scheduler { for (i, task) in self.tasks.iter_mut().enumerate() { let poll = task.poll(); if let TaskState::Ready(position) = poll { - let closest_turtle = match free_turtles.iter_mut().zip(turtle_positions.iter()).min_by_key( |(_,p)| { + let closest_turtle = match free_turtles.iter_mut().zip(turtle_positions.iter()) + .filter(|t|t.0.1.is_none()) // Don't double-schedule + .min_by_key( |(_,p)| { p.manhattan(position) }) { Some(turtle) => turtle.0, None => break, }; + trace!("scheduling task on #{}", closest_turtle.0.name().to_num()); closest_turtle.1 = Some(task.run(closest_turtle.0.clone())); } if let TaskState::Complete = poll { @@ -98,7 +102,10 @@ impl Scheduler { } pub async fn cancel(&mut self, turtle: Name) -> Option<()> { - self.turtles.iter_mut().find(|t| t.0.name() == turtle)?.1.take()?.abort(); + if let Some(task) = self.turtles.iter_mut().find(|t| t.0.name() == turtle)?.1.as_ref() { + task.abort(); + info!("aborted task for #{}", turtle.to_num()); + } Some(()) } }