Improve pool

This commit is contained in:
Maximilian Ammann 2021-12-29 22:20:37 +01:00
parent f029c1efc4
commit 184f37df44
2 changed files with 53 additions and 32 deletions

View File

@ -1,12 +1,16 @@
use std::collections::VecDeque;
use std::io::Cursor;
use std::sync::{Arc, Condvar, Mutex};
use log::info;
use lyon::tessellation::VertexBuffers;
use vector_tile::parse_tile_reader;
use vector_tile::tile::Tile;
use crate::io::{static_database, TileCoords}; use crate::io::{static_database, TileCoords};
use crate::render::shader_ffi::GpuVertexUniform; use crate::render::shader_ffi::GpuVertexUniform;
use crate::tesselation::{IndexDataType, Tesselated}; use crate::tesselation::{IndexDataType, Tesselated};
use lyon::tessellation::VertexBuffers;
use std::collections::VecDeque;
use std::io::Cursor;
use std::sync::{Arc, Mutex};
use vector_tile::parse_tile_reader;
use vector_tile::tile::Tile;
#[derive(Clone)] #[derive(Clone)]
pub struct TesselatedTile { pub struct TesselatedTile {
@ -16,27 +20,29 @@ pub struct TesselatedTile {
#[derive(Clone)] #[derive(Clone)]
pub struct Pool { pub struct Pool {
requests: WorkQueue<TileCoords>, requests: Arc<WorkQueue<TileCoords>>,
responses: WorkQueue<TesselatedTile>, responses: Arc<WorkQueue<TesselatedTile>>,
} }
impl Pool { impl Pool {
pub fn new() -> Self { pub fn new() -> Self {
Self { Self {
requests: WorkQueue::new(), requests: Arc::new(WorkQueue::new()),
responses: WorkQueue::new(), responses: Arc::new(WorkQueue::new()),
} }
} }
pub fn fetch(&self, coords: TileCoords) { pub fn fetch(&self, coords: TileCoords) {
info!("new tile request: {:?}", &coords);
self.requests.push(coords); self.requests.push(coords);
} }
pub fn get_available(&self) -> Vec<TesselatedTile> { pub fn pop_all(&self) -> Vec<TesselatedTile> {
self.responses.pop_all() self.responses.try_pop_all()
} }
pub fn run_loop(&self) { pub fn run_loop(&self) {
loop {
while let Some(coords) = self.requests.pop() { while let Some(coords) = self.requests.pop() {
if let Some(file) = static_database::get_tile(&coords) { if let Some(file) = static_database::get_tile(&coords) {
let tile = parse_tile_reader(&mut Cursor::new(file.contents())) let tile = parse_tile_reader(&mut Cursor::new(file.contents()))
@ -51,26 +57,31 @@ impl Pool {
) )
}; };
self.responses.push(TesselatedTile { coords, geometry }); self.responses.push(TesselatedTile { coords, geometry });
info!("tile ready: {:?}", &coords);
} else {
info!("tile failed: {:?}", &coords);
}
} }
} }
} }
} }
#[derive(Clone)]
struct WorkQueue<T: Send> { struct WorkQueue<T: Send> {
inner: Arc<Mutex<VecDeque<T>>>, inner: Mutex<VecDeque<T>>,
cvar: Condvar,
} }
impl<T: Send> WorkQueue<T> { impl<T: Send> WorkQueue<T> {
fn new() -> Self { fn new() -> Self {
Self { Self {
inner: Arc::new(Mutex::new(VecDeque::new())), inner: Mutex::new(VecDeque::new()),
cvar: Condvar::new(),
} }
} }
fn pop_all(&self) -> Vec<T> { fn try_pop_all(&self) -> Vec<T> {
let mut result = Vec::new(); let mut result = Vec::new();
if let Ok(mut queue) = self.inner.lock() { if let Ok(mut queue) = self.inner.try_lock() {
while let Some(element) = queue.pop_front() { while let Some(element) = queue.pop_front() {
result.push(element); result.push(element);
} }
@ -87,7 +98,12 @@ impl<T: Send> WorkQueue<T> {
fn pop(&self) -> Option<T> { fn pop(&self) -> Option<T> {
if let Ok(mut queue) = self.inner.lock() { if let Ok(mut queue) = self.inner.lock() {
queue.pop_front() loop {
match queue.pop_front() {
Some(element) => return Some(element),
None => queue = self.cvar.wait(queue).unwrap(),
}
}
} else { } else {
panic!("locking failed"); panic!("locking failed");
} }
@ -96,6 +112,7 @@ impl<T: Send> WorkQueue<T> {
fn push(&self, work: T) -> usize { fn push(&self, work: T) -> usize {
if let Ok(mut queue) = self.inner.lock() { if let Ok(mut queue) = self.inner.lock() {
queue.push_back(work); queue.push_back(work);
self.cvar.notify_all();
queue.len() queue.len()
} else { } else {
panic!("locking failed"); panic!("locking failed");

View File

@ -10,7 +10,11 @@ use crate::render::state::State;
pub async fn setup(window: winit::window::Window, event_loop: EventLoop<()>, pool: Pool) { pub async fn setup(window: winit::window::Window, event_loop: EventLoop<()>, pool: Pool) {
info!("== mapr =="); info!("== mapr ==");
pool.fetch((2179, 1421, 12).into()); for x in 0..10 {
for y in 0..10 {
pool.fetch((2179 + x, 1421 + y, 12).into())
}
}
let mut input = InputHandler::new(); let mut input = InputHandler::new();
let mut state = State::new(&window).await; let mut state = State::new(&window).await;