use parking_lot::RwLock;
use rm_lisa::{
initialize_logging,
tasks::{LisaTaskId, LisaTaskStatus, TaskEvent, TaskEventLogProvider, ThreadOrTokioTaskId},
};
use std::{
sync::{
Arc,
atomic::{AtomicU8, Ordering},
},
time::Duration,
};
use tokio::{signal::ctrl_c, time::sleep};
use tracing::info;
#[tokio::main]
pub async fn main() {
let task_provider = GlobalTaskList::spawn_tasks();
let console = initialize_logging("task-display").expect("Failed to initialize logging!");
console.set_task_provider(task_provider.clone());
loop {
if task_provider.tasks_running() {
info!("[/] Waiting for tasks to complete!");
} else {
info!("[+] Done!");
break;
}
tokio::select! {
_ = sleep(Duration::from_secs(1)) => {}
_ = ctrl_c() => {
break;
}
}
}
console.flush().await;
}
#[derive(Clone)]
struct GlobalTaskList(Arc<RwLock<Vec<TaskEvent>>>, Arc<AtomicU8>);
impl GlobalTaskList {
pub fn spawn_tasks() -> Self {
let events = Arc::new(RwLock::new(Vec::new()));
let tasks_left = Arc::new(AtomicU8::new(5));
Self::simple_bg_task(
(1, 1),
"smol computation".to_owned(),
vec![(
Duration::from_secs(1),
LisaTaskStatus::Waiting(Some("cleanup".to_owned())),
)],
events.clone(),
tasks_left.clone(),
);
Self::simple_bg_task(
(1, 2),
"fetch".to_owned(),
vec![
(
Duration::from_secs(1),
LisaTaskStatus::Waiting(Some("network response".to_owned())),
),
(
Duration::from_secs(1),
LisaTaskStatus::Running(Some("parsing network response".to_owned())),
),
(
Duration::from_secs(3),
LisaTaskStatus::Waiting(Some("cleanup".to_owned())),
),
],
events.clone(),
tasks_left.clone(),
);
Self::simple_bg_task(
(1, 3),
"processing".to_owned(),
vec![(
Duration::from_secs(5),
LisaTaskStatus::Waiting(Some("cleanup".to_owned())),
)],
events.clone(),
tasks_left.clone(),
);
Self::simple_bg_task(
(2, 1),
"smol 2".to_owned(),
vec![(
Duration::from_secs(1),
LisaTaskStatus::Waiting(Some("cleanup".to_owned())),
)],
events.clone(),
tasks_left.clone(),
);
Self::simple_bg_task(
(3, 1),
"smol 3".to_owned(),
vec![(
Duration::from_secs(1),
LisaTaskStatus::Waiting(Some("cleanup".to_owned())),
)],
events.clone(),
tasks_left.clone(),
);
Self(events, tasks_left)
}
#[must_use]
pub fn tasks_running(&self) -> bool {
self.1.load(Ordering::SeqCst) != 0
}
fn simple_bg_task(
ids: (u64, u64),
name: String,
task_waits: Vec<(Duration, LisaTaskStatus)>,
events: Arc<RwLock<Vec<TaskEvent>>>,
tasks: Arc<AtomicU8>,
) {
_ = tokio::task::spawn(async move {
sleep(Duration::from_secs(1)).await;
{
let mut event_lock = events.write();
event_lock.push(TaskEvent::TaskStart(
ThreadOrTokioTaskId(ids.0),
LisaTaskId(ids.1),
name,
LisaTaskStatus::Running(None),
));
}
for (wait_before, status_after) in task_waits {
sleep(wait_before).await;
{
let mut event_lock = events.write();
event_lock.push(TaskEvent::TaskStatusUpdate(
ThreadOrTokioTaskId(ids.0),
LisaTaskId(ids.1),
status_after,
));
}
}
sleep(Duration::from_secs(1)).await;
{
let mut event_lock = events.write();
event_lock.push(TaskEvent::TaskEnd(
ThreadOrTokioTaskId(ids.0),
LisaTaskId(ids.1),
));
}
_ = tasks.fetch_sub(1, Ordering::SeqCst);
});
}
}
impl TaskEventLogProvider for GlobalTaskList {
fn new_events(&self) -> Vec<TaskEvent> {
let events = {
let mut locked = self.0.write();
locked.drain(..).collect::<Vec<_>>()
};
events
}
}