Async Entity Component System based on the ideas of specs (https://github.com/amethyst/specs)
25개 이상의 토픽을 선택하실 수 없습니다. Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

91 lines
2.3 KiB

  1. use std::mem::transmute;
  2. use futures::{
  3. executor::block_on,
  4. future::{BoxFuture, Future, FutureExt},
  5. join,
  6. };
  7. use tokio::task::{block_in_place, spawn};
  8. use parallel_iterator::{
  9. Consumer, Executor, Folder, IndexedConsumer, IndexedProducer, Producer, Reducer,
  10. };
  11. pub struct TokioExecutor;
  12. impl Executor for TokioExecutor {
  13. fn exec<P, C>(self, producer: P, consumer: C) -> C::Result
  14. where
  15. P: Producer,
  16. C: Consumer<P::Item>,
  17. {
  18. block_in_place(|| block_on(exec(2 * num_cpus::get(), producer, consumer)))
  19. }
  20. fn exec_indexed<P, C>(self, producer: P, consumer: C) -> C::Result
  21. where
  22. P: IndexedProducer,
  23. C: IndexedConsumer<P::Item>,
  24. {
  25. let _producer = producer;
  26. let _consumer = consumer;
  27. unimplemented!()
  28. }
  29. }
  30. fn exec<'a, P, C>(splits: usize, producer: P, consumer: C) -> BoxFuture<'a, C::Result>
  31. where
  32. P: Producer + 'a,
  33. C: Consumer<P::Item> + 'a,
  34. {
  35. async move {
  36. if consumer.is_full() {
  37. consumer.into_folder().complete()
  38. } else if splits > 0 {
  39. match producer.split() {
  40. (left_producer, Some(right_producer)) => {
  41. let ((left_consumer, reducer), right_consumer) =
  42. (consumer.split_off_left(), consumer);
  43. let left = run_as_task(exec(splits / 2, left_producer, left_consumer));
  44. let right = run_as_task(exec(splits / 2, right_producer, right_consumer));
  45. let (left_result, right_result) = join!(left, right);
  46. reducer.reduce(left_result, right_result)
  47. }
  48. (producer, None) => producer.fold_with(consumer.into_folder()).complete(),
  49. }
  50. } else {
  51. producer.fold_with(consumer.into_folder()).complete()
  52. }
  53. }
  54. .boxed()
  55. }
  56. struct Pointer<T>(*mut T);
  57. unsafe impl<T> Send for Pointer<T> {}
  58. async fn run_as_task<'a, T, F>(f: F) -> T
  59. where
  60. T: Send + 'a,
  61. F: Future<Output = T> + Send + 'a,
  62. {
  63. let mut result = None;
  64. let r = Pointer(&mut result as *mut _);
  65. let task: BoxFuture<'a, ()> = async move {
  66. unsafe {
  67. *r.0 = Some(f.await);
  68. }
  69. }
  70. .boxed();
  71. let task: BoxFuture<'static, ()> = unsafe { transmute(task) };
  72. spawn(task).await.expect("Error in iterator executor");
  73. result.unwrap()
  74. }