|
| 1 | +use std::{collections::VecDeque, sync::Arc}; |
| 2 | + |
| 3 | +use anyhow::Result; |
| 4 | + |
| 5 | +use super::executor_graph::ExecutorGraph; |
| 6 | +use super::executor_task::ExecutionTask; |
| 7 | +use super::parallel::pipeline_builder::PipelineBuilder; |
| 8 | +use super::physical::PhysicalOperatorRef; |
| 9 | +use super::runtime::thread::Thread; |
| 10 | +use super::runtime::thread::ThreadJoinHandle; |
| 11 | +use super::runtime::ExecutionRuntime; |
| 12 | +use super::runtime::TrySpawn; |
| 13 | + |
| 14 | +pub struct ExecutionQueue(pub VecDeque<ExecutionTask>); |
| 15 | + |
| 16 | +impl ExecutionQueue { |
| 17 | + pub fn push_task(&mut self, task: ExecutionTask) { |
| 18 | + self.0.push_back(task); |
| 19 | + } |
| 20 | +} |
| 21 | + |
| 22 | +pub struct ExecutionContext { |
| 23 | + pub global_execution_queue: ExecutionQueue, |
| 24 | +} |
| 25 | + |
| 26 | +impl ExecutionContext { |
| 27 | + pub fn get_global_execution_queue(&mut self) -> &mut ExecutionQueue { |
| 28 | + &mut self.global_execution_queue |
| 29 | + } |
| 30 | +} |
| 31 | + |
| 32 | +pub struct Executor { |
| 33 | + pub context: ExecutionContext, |
| 34 | + pub graph: ExecutorGraph, |
| 35 | + pub threads_num: usize, |
| 36 | + pub runtime: Arc<ExecutionRuntime>, |
| 37 | +} |
| 38 | + |
| 39 | +impl Executor { |
| 40 | + pub async fn initialize(plan: PhysicalOperatorRef) -> Result<Executor> { |
| 41 | + let mut builder = PipelineBuilder::new(); |
| 42 | + let meta_pipeline = builder.finalize(plan)?; |
| 43 | + |
| 44 | + let graph = ExecutorGraph::from_pipeline(meta_pipeline)?; |
| 45 | + |
| 46 | + Ok(Executor { |
| 47 | + context: ExecutionContext { |
| 48 | + global_execution_queue: ExecutionQueue(VecDeque::new()), |
| 49 | + }, |
| 50 | + graph, |
| 51 | + threads_num: 0, |
| 52 | + runtime: Arc::new(ExecutionRuntime::with_default_worker_threads()?), |
| 53 | + }) |
| 54 | + } |
| 55 | + |
| 56 | + pub async fn execute(&mut self) -> Result<()> { |
| 57 | + // Schedule the pipelines that do not have dependencies. |
| 58 | + self.graph |
| 59 | + .init_schedule_event_queue(&mut self.context.global_execution_queue) |
| 60 | + .await; |
| 61 | + |
| 62 | + // Pull execution task from `GlobalExecutionQueue`. |
| 63 | + self.runtime.spawn(ExecutionTask::empty()); |
| 64 | + Ok(()) |
| 65 | + } |
| 66 | + |
| 67 | + fn execute_threads(self: &Arc<Self>) -> Vec<ThreadJoinHandle<Result<()>>> { |
| 68 | + let mut thread_join_handles = Vec::with_capacity(self.threads_num); |
| 69 | + for thread_num in 0..self.threads_num { |
| 70 | + let this = self.clone(); |
| 71 | + #[allow(unused_mut)] |
| 72 | + let mut name = Some(format!("PipelineTask-{}", thread_num)); |
| 73 | + |
| 74 | + thread_join_handles.push(Thread::named_spawn(name, move || unsafe { |
| 75 | + // let this_clone = this.clone(); |
| 76 | + |
| 77 | + // let try_result = catch_unwind(move || -> Result<()> { |
| 78 | + // match this_clone.execute_single_thread(thread_num) { |
| 79 | + // Ok(_) => Ok(()), |
| 80 | + // Err(cause) => Err(cause), |
| 81 | + // } |
| 82 | + // }); |
| 83 | + |
| 84 | + // // finish the pipeline executor when has error or panic |
| 85 | + // if let Err(cause) = try_result.flatten() { |
| 86 | + // // this.finish(Some(cause)); |
| 87 | + // } |
| 88 | + |
| 89 | + Ok(()) |
| 90 | + })); |
| 91 | + } |
| 92 | + thread_join_handles |
| 93 | + } |
| 94 | + |
| 95 | + unsafe fn execute_single_thread(&self, thread_num: usize) -> Result<()> { |
| 96 | + Ok(()) |
| 97 | + } |
| 98 | + |
| 99 | + fn complete_pipeline(&self) {} |
| 100 | + |
| 101 | + fn finish_task(&self) -> Result<()> { |
| 102 | + Ok(()) |
| 103 | + } |
| 104 | +} |
0 commit comments