1
Fork 0

depot semaphore

This commit is contained in:
Andy Killorin 2023-12-26 09:14:28 -06:00
parent 9859f64d65
commit 42ef46f2ff
Signed by: ank
GPG key ID: B6241CA3B552BCA4
3 changed files with 26 additions and 11 deletions

View file

@ -1,7 +1,7 @@
use std::sync::Arc; use std::sync::Arc;
use tracing::{warn, info, trace}; use tracing::{warn, info, trace};
use tokio::sync::{Mutex, OwnedMutexGuard}; use tokio::sync::{Mutex, OwnedMutexGuard, Semaphore};
use crate::{blocks::Position, turtle::TurtleCommander}; use crate::{blocks::Position, turtle::TurtleCommander};
use crate::turtle::{TurtleCommand::*, TurtleCommandResponse}; use crate::turtle::{TurtleCommand::*, TurtleCommandResponse};
@ -13,7 +13,8 @@ use crate::turtle::{TurtleCommand::*, TurtleCommandResponse};
/// ahead of the specified position is a chest of combustibles /// ahead of the specified position is a chest of combustibles
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
pub struct Depots { pub struct Depots {
depots: Arc<Mutex<Vec<Arc<Mutex<Position>>>>> depots: Arc<Mutex<Vec<Arc<Mutex<Position>>>>>,
depot_semaphore: Arc<Semaphore>,
} }
impl Depots { impl Depots {
@ -27,6 +28,7 @@ impl Depots {
} }
pub async fn dock(&self, turtle: TurtleCommander) -> Option<usize> { pub async fn dock(&self, turtle: TurtleCommander) -> Option<usize> {
let permit = self.depot_semaphore.clone().acquire_owned().await.unwrap();
let depot = self.clone().nearest(turtle.pos().await).await?; let depot = self.clone().nearest(turtle.pos().await).await?;
trace!("depot at {depot:?}"); trace!("depot at {depot:?}");
turtle.goto(*depot).await?; turtle.goto(*depot).await?;
@ -54,23 +56,27 @@ impl Depots {
} }
} }
} }
// This can fail, we don't really care (as long as it executes once)
turtle.execute(Backward(4)).await;
drop(depot);
drop(permit);
// lava bucket fix // lava bucket fix
for i in 1..=16 { for i in 1..=16 {
turtle.execute(Select(i)).await; turtle.execute(Select(i)).await;
turtle.execute(DropDown(64)).await; turtle.execute(DropDown(64)).await;
} }
turtle.execute(Backward(1)).await;
drop(depot); // assumes that the turtle will very quickly leave
Some(turtle.fuel()) Some(turtle.fuel())
} }
pub async fn add(&self, pos: Position) { pub async fn add(&self, pos: Position) {
info!("new depot at {pos:?}"); info!("new depot at {pos:?}");
self.depots.lock().await.push(Arc::new(Mutex::new(pos))) self.depots.lock().await.push(Arc::new(Mutex::new(pos)));
self.depot_semaphore.add_permits(1);
} }
pub fn from_vec(vec: Vec<Position>) -> Self { pub fn from_vec(vec: Vec<Position>) -> Self {
@ -78,7 +84,10 @@ impl Depots {
for depot in vec { for depot in vec {
depots.push(Arc::new(Mutex::new(depot))); depots.push(Arc::new(Mutex::new(depot)));
} }
Depots { depots: Arc::new(Mutex::new(depots)) } let permits = depots.len();
Depots { depots: Arc::new(Mutex::new(depots)),
depot_semaphore: Arc::new(Semaphore::new(permits))
}
} }
pub async fn to_vec(self) -> Vec<Position> { pub async fn to_vec(self) -> Vec<Position> {

View file

@ -71,7 +71,7 @@ pub async fn mine_chunk_and_sweep(turtle: TurtleCommander, pos: Vec3, chunk: Vec
} }
async fn near_valuables(turtle: &TurtleCommander, pos: Vec3, chunk: Vec3) -> Vec<Vec3> { async fn near_valuables(turtle: &TurtleCommander, pos: Vec3, chunk: Vec3) -> Vec<Vec3> {
let scan = (0..=(chunk*2).product()).map(|n| fill(chunk * 2, n) - chunk/2); let scan = (0..(chunk*2).product()).map(|n| fill(chunk * 2, n) - chunk/2);
let world = turtle.world().lock().await; let world = turtle.world().lock().await;
scan.map(|n| world.get(n)) scan.map(|n| world.get(n))

View file

@ -348,10 +348,16 @@ pub(crate) async fn process_turtle_update(
state: &LiveState, state: &LiveState,
update: TurtleUpdate, update: TurtleUpdate,
) -> Option<TurtleCommand> { ) -> Option<TurtleCommand> {
let mut turtle = state let mut turtle = match state
.turtles .turtles
.get(id as usize) .get(id as usize) {
.context("nonexisting turtle").unwrap().write().await; Some(turtle) => turtle.write().await,
None => {
error!("nonexisting turtle {id}");
return Some(TurtleCommand::Poweroff);
},
};
let world = &state.world; let world = &state.world;
if turtle.pending_update { if turtle.pending_update {