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.

114 lines
2.5 KiB

  1. use std::cell::UnsafeCell;
  2. use hibitset::BitSetLike;
  3. use parallel_iterator::{Consumer, Executor, Folder, ParallelIterator, Producer};
  4. use crate::misc::{BitIter, BitProducer, TokioExecutor};
  5. use super::Join;
  6. pub trait ParJoin: Join {
  7. fn par_join(self) -> JoinParIter<Self>
  8. where
  9. Self: Sized,
  10. {
  11. if <Self as Join>::is_unconstrained() {
  12. log::warn!(
  13. "`ParJoin` possibly iterating through all indices, you might've made a join with all `MaybeJoin`s, which is unbounded in length."
  14. );
  15. }
  16. JoinParIter(self)
  17. }
  18. }
  19. pub struct JoinParIter<J>(J);
  20. impl<J> ParallelIterator for JoinParIter<J>
  21. where
  22. J: Join + Send,
  23. J::Type: Send,
  24. J::Mask: Send + Sync,
  25. J::Value: Send,
  26. {
  27. type Item = J::Type;
  28. fn drive<C>(self, consumer: C) -> C::Result
  29. where
  30. C: Consumer<Self::Item>,
  31. {
  32. let (keys, values) = self.0.open();
  33. let values = UnsafeCell::new(values);
  34. let keys = BitIter::new(&keys, [0, 0, 0, keys.layer3()], [0; 3]);
  35. let producer = BitProducer::new(keys, 3);
  36. let producer = JoinProducer::<J>::new(producer, &values);
  37. TokioExecutor.exec(producer, consumer)
  38. }
  39. }
  40. struct JoinProducer<'a, J>
  41. where
  42. J: Join + Send,
  43. J::Type: Send,
  44. J::Mask: Send,
  45. J::Value: Send,
  46. {
  47. pub(crate) keys: BitProducer<'a, J::Mask>,
  48. pub(crate) values: &'a UnsafeCell<J::Value>,
  49. }
  50. impl<'a, J> JoinProducer<'a, J>
  51. where
  52. J: Join + Send,
  53. J::Type: Send,
  54. J::Mask: Send,
  55. J::Value: Send,
  56. {
  57. fn new(keys: BitProducer<'a, J::Mask>, values: &'a UnsafeCell<J::Value>) -> Self {
  58. JoinProducer { keys, values }
  59. }
  60. }
  61. unsafe impl<'a, J> Send for JoinProducer<'a, J>
  62. where
  63. J: Join + Send,
  64. J::Type: Send,
  65. J::Value: Send + 'a,
  66. J::Mask: Send + Sync + 'a,
  67. {
  68. }
  69. impl<'a, J> Producer for JoinProducer<'a, J>
  70. where
  71. J: Join + Send,
  72. J::Type: Send,
  73. J::Value: Send + 'a,
  74. J::Mask: Send + Sync + 'a,
  75. {
  76. type Item = J::Type;
  77. fn split(self) -> (Self, Option<Self>) {
  78. let (cur, other) = self.keys.split();
  79. let values = self.values;
  80. let first = JoinProducer::new(cur, values);
  81. let second = other.map(|o| JoinProducer::new(o, values));
  82. (first, second)
  83. }
  84. fn fold_with<F>(self, folder: F) -> F
  85. where
  86. F: Folder<Self::Item>,
  87. {
  88. let JoinProducer { values, keys, .. } = self;
  89. let iter = keys
  90. .iter
  91. .map(|idx| unsafe { J::get(&mut *values.get(), idx) });
  92. folder.consume_iter(iter)
  93. }
  94. }