89 lines
2.2 KiB
Rust
89 lines
2.2 KiB
Rust
// engine
|
|
use engine::prelude::*;
|
|
|
|
// std
|
|
use std::mem;
|
|
use std::sync::{Arc, Mutex, RwLock};
|
|
|
|
use super::map_db::MapDataBase;
|
|
|
|
// sql
|
|
use anyhow::Result;
|
|
|
|
pub struct AsyncDBAccess {
|
|
sql: Arc<Mutex<MapDataBase>>,
|
|
async_thread: RwLock<AsyncThread<Result<()>>>,
|
|
queue: RwLock<Vec<DispatchCommand>>,
|
|
}
|
|
|
|
impl AsyncDBAccess {
|
|
pub fn new(map_db: MapDataBase) -> AsyncDBAccess {
|
|
AsyncDBAccess {
|
|
sql: Arc::new(Mutex::new(map_db)),
|
|
async_thread: RwLock::new(AsyncThread::spawn(move || Ok(()))),
|
|
queue: RwLock::new(Vec::new()),
|
|
}
|
|
}
|
|
|
|
pub fn add<F>(&self, f: F) -> Result<()>
|
|
where
|
|
F: FnOnce(&MapDataBase) -> Result<()> + Send + Sync + 'static,
|
|
{
|
|
let sql_clone = self.sql.clone();
|
|
self.queue
|
|
.write()
|
|
.unwrap()
|
|
.push(DispatchCommand::new(sql_clone, f));
|
|
Ok(())
|
|
}
|
|
|
|
pub fn dispatch(&self) -> Result<()> {
|
|
let mut async_thread = self.async_thread.write().unwrap();
|
|
let mut queue = self.queue.write().unwrap();
|
|
|
|
// check if async thread is returned
|
|
if async_thread.check()? {
|
|
// check if there are calls to be dispatched
|
|
if !queue.is_empty() {
|
|
// move calls into queue to call it in a thread
|
|
let mut dispatch_queue = Vec::new();
|
|
mem::swap(&mut dispatch_queue, &mut queue);
|
|
|
|
*async_thread = AsyncThread::spawn(move || {
|
|
for dispatch_call in dispatch_queue {
|
|
dispatch_call.call()?;
|
|
}
|
|
|
|
Ok(())
|
|
});
|
|
}
|
|
}
|
|
|
|
Ok(())
|
|
}
|
|
}
|
|
|
|
unsafe impl Sync for AsyncDBAccess {}
|
|
|
|
struct DispatchCommand {
|
|
sql: Arc<Mutex<MapDataBase>>,
|
|
command: Box<dyn FnOnce(&MapDataBase) -> Result<()> + Send + Sync>,
|
|
}
|
|
|
|
impl DispatchCommand {
|
|
pub fn new<F>(sql: Arc<Mutex<MapDataBase>>, command: F) -> Self
|
|
where
|
|
F: FnOnce(&MapDataBase) -> Result<()> + Send + Sync + 'static,
|
|
{
|
|
DispatchCommand {
|
|
sql,
|
|
command: Box::new(command),
|
|
}
|
|
}
|
|
|
|
pub fn call(self) -> Result<()> {
|
|
let sql_lock = self.sql.lock().unwrap();
|
|
|
|
(self.command)(&*sql_lock)
|
|
}
|
|
}
|