builder.rs 1.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263
  1. use super::{Executor, OutputHandle, RealExecutor, Stack};
  2. use crate::context::ExecutionContext;
  3. use alloc::{boxed::Box, sync::Arc};
  4. use core::{pin::Pin, sync::atomic::AtomicBool};
  5. use eonix_sync::Spin;
  6. pub struct ExecutorBuilder<S, R> {
  7. stack: Option<S>,
  8. runnable: Option<R>,
  9. }
  10. impl<S, R> ExecutorBuilder<S, R>
  11. where
  12. S: Stack,
  13. R::Output: Send,
  14. {
  15. pub fn new() -> Self {
  16. Self {
  17. stack: None,
  18. runnable: None,
  19. }
  20. }
  21. pub fn stack(mut self, stack: S) -> Self {
  22. self.stack.replace(stack);
  23. self
  24. }
  25. pub fn runnable(mut self, runnable: R) -> Self {
  26. self.runnable.replace(runnable);
  27. self
  28. }
  29. pub fn build(
  30. mut self,
  31. ) -> (
  32. Pin<Box<impl Executor>>,
  33. ExecutionContext,
  34. Arc<Spin<OutputHandle<R::Output>>>,
  35. ) {
  36. let stack = self.stack.take().expect("Stack is required");
  37. let runnable = self.runnable.take().expect("Runnable is required");
  38. let mut execution_context = ExecutionContext::new();
  39. let output_handle = OutputHandle::new();
  40. execution_context.set_sp(stack.get_bottom().addr().get() as _);
  41. let executor = Box::pin(RealExecutor {
  42. _stack: stack,
  43. runnable,
  44. output_handle: Arc::downgrade(&output_handle),
  45. finished: AtomicBool::new(false),
  46. });
  47. execution_context.call1(
  48. RealExecutor::<S, R>::execute,
  49. executor.as_ref().get_ref() as *const _ as usize,
  50. );
  51. (executor, execution_context, output_handle)
  52. }
  53. }