use parking_lot::RwLock;
use std::path::PathBuf;
use std::sync::Arc;
use crate::environment::Environment;
use crate::plugins::{InitializedPlugin, InitializedPluginPool};
use super::{FormattingFilePathInfo, LocalPluginWork, LocalWork, LocalWorkStealInfo};
pub struct StealResult<TEnvironment: Environment> {
pub plugin: Option<Box<dyn InitializedPlugin>>,
pub work: LocalPluginWork<TEnvironment>,
}
pub struct Worker<TEnvironment: Environment> {
pub id: usize,
local_work: RwLock<LocalWork<TEnvironment>>,
}
impl<TEnvironment: Environment> Worker<TEnvironment> {
pub fn new(id: usize, work_by_plugin: Vec<LocalPluginWork<TEnvironment>>) -> Self {
Worker {
id,
local_work: RwLock::new(LocalWork::new(work_by_plugin)),
}
}
pub fn get_current_formatting_file_path_info(&self) -> Option<FormattingFilePathInfo> {
self.local_work.read().get_current_formatting_file_path_info()
}
pub fn has_pool(&self, pool_name: &str) -> bool {
let local_work = self.local_work.read();
for work in local_work.work_by_plugin.iter() {
if work.pool.name() == pool_name {
return true;
}
}
false
}
pub fn calculate_worthwhile_steal_time(&self) -> Option<LocalWorkStealInfo> {
self.local_work.read().calculate_worthwhile_steal_time()
}
pub fn try_steal(&self, steal_info: LocalWorkStealInfo) -> Option<StealResult<TEnvironment>> {
let mut local_work = self.local_work.write();
if local_work.stealer_id != steal_info.stealer_id {
return None; }
if local_work.work_by_plugin.len() > 1 {
let steal_result = StealResult {
plugin: None,
work: local_work.work_by_plugin.pop().unwrap(),
};
local_work.stealer_id += 1;
Some(steal_result)
} else if let Some(plugin_work) = local_work.work_by_plugin.get_mut(0) {
if plugin_work.work_items_len() > 1 {
let plugin = if steal_info.has_plugin_available() {
match plugin_work.pool.take_if_available() {
Some(plugin) => Some(plugin),
None => return None, }
} else {
None
};
let steal_result = StealResult {
plugin,
work: plugin_work.split(),
};
local_work.stealer_id += 1;
Some(steal_result)
} else {
None
}
} else {
None
}
}
pub fn add_work(&self, work: LocalPluginWork<TEnvironment>) {
self.local_work.write().work_by_plugin.push(work);
}
pub fn take_next_work(&self) -> Option<(Arc<InitializedPluginPool<TEnvironment>>, PathBuf)> {
let mut local_work = self.local_work.write();
if let Some(work_by_plugin) = local_work.work_by_plugin.get_mut(0) {
let pool = work_by_plugin.pool.clone();
let file_path = work_by_plugin.take_next_work_item();
if work_by_plugin.work_items_len() == 0 {
local_work.work_by_plugin.remove(0);
}
local_work.set_current_formatting_file_path(file_path.clone());
Some((pool, file_path))
} else {
local_work.clear_current_formatting_file_path();
None
}
}
pub fn clear_work_for_current_plugin(&self) {
let mut local_work = self.local_work.write();
if !local_work.work_by_plugin.is_empty() {
local_work.work_by_plugin.remove(0);
}
}
}