Async Entity Component System based on the ideas of specs (https://github.com/amethyst/specs)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

118 lines
2.3 KiB

  1. use crate::{core::Driver, Consumer, Executor, Folder, ParallelIterator};
  2. use super::noop::NoOpReducer;
  3. pub struct ForEach<X, O> {
  4. iterator: X,
  5. operation: O,
  6. }
  7. impl<X, O> ForEach<X, O> {
  8. pub fn new(iterator: X, operation: O) -> Self {
  9. Self {
  10. iterator,
  11. operation,
  12. }
  13. }
  14. }
  15. impl<'a, X, O> Driver<'a, ()> for ForEach<X, O>
  16. where
  17. X: ParallelIterator<'a>,
  18. O: Fn(X::Item) + Clone + Send + 'a,
  19. {
  20. fn exec_with<E>(self, executor: E) -> E::Result
  21. where
  22. E: Executor<'a, ()>,
  23. {
  24. let iterator = self.iterator;
  25. let operation = self.operation;
  26. let consumer = ForEachConsumer { operation };
  27. iterator.drive(executor, consumer)
  28. }
  29. }
  30. pub struct ForEachConsumer<O> {
  31. operation: O,
  32. }
  33. impl<O, I> Consumer<I> for ForEachConsumer<O>
  34. where
  35. O: Fn(I) + Clone + Send,
  36. {
  37. type Folder = ForEachConsumer<O>;
  38. type Reducer = NoOpReducer;
  39. type Result = ();
  40. fn split_off_left(&self) -> (Self, NoOpReducer) {
  41. (
  42. ForEachConsumer {
  43. operation: self.operation.clone(),
  44. },
  45. NoOpReducer,
  46. )
  47. }
  48. fn into_folder(self) -> Self {
  49. self
  50. }
  51. }
  52. impl<O, I> Folder<I> for ForEachConsumer<O>
  53. where
  54. O: Fn(I),
  55. {
  56. type Result = ();
  57. fn consume(self, item: I) -> Self {
  58. (self.operation)(item);
  59. self
  60. }
  61. fn consume_iter<X>(self, iter: X) -> Self
  62. where
  63. X: IntoIterator<Item = I>,
  64. {
  65. iter.into_iter().for_each(&self.operation);
  66. self
  67. }
  68. fn complete(self) {}
  69. }
  70. #[cfg(test)]
  71. mod tests {
  72. use super::*;
  73. use crate::*;
  74. #[tokio::test]
  75. async fn test_for_each() {
  76. use ::std::sync::atomic::{AtomicUsize, Ordering};
  77. use ::std::sync::Arc;
  78. let i = Arc::new(AtomicUsize::new(0));
  79. let j = Arc::new(AtomicUsize::new(0));
  80. let x = (0..10usize)
  81. .into_par_iter()
  82. .map_init(
  83. move || i.fetch_add(1, Ordering::Relaxed),
  84. |init, item| Some((*init, item)),
  85. )
  86. .for_each_init(
  87. move || j.fetch_add(1, Ordering::Relaxed),
  88. |init, item| {
  89. println!("{:?} {:?}", init, item);
  90. },
  91. )
  92. .exec()
  93. .await;
  94. dbg!(x);
  95. }
  96. }