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.

318 regels
7.0 KiB

  1. use std::sync::{
  2. atomic::{AtomicUsize, Ordering},
  3. Arc,
  4. };
  5. use crate::{Consumer, Driver, Executor, Folder, ParallelIterator, Reducer};
  6. #[derive(Copy, Clone, Eq, PartialEq)]
  7. pub enum FindMatch {
  8. Any,
  9. First,
  10. Last,
  11. }
  12. /* Find */
  13. pub struct Find<X, O> {
  14. iterator: X,
  15. operation: O,
  16. find_match: FindMatch,
  17. }
  18. impl<X, O> Find<X, O> {
  19. pub fn new(iterator: X, operation: O, find_match: FindMatch) -> Self {
  20. Self {
  21. iterator,
  22. operation,
  23. find_match,
  24. }
  25. }
  26. }
  27. impl<'a, X, O> Driver<'a, Option<X::Item>> for Find<X, O>
  28. where
  29. X: ParallelIterator<'a>,
  30. O: Fn(&X::Item) -> bool + Clone + Send + 'a,
  31. {
  32. fn exec_with<E>(self, executor: E) -> E::Result
  33. where
  34. E: Executor<'a, Option<X::Item>>,
  35. {
  36. let consumer = FindConsumer {
  37. operation: self.operation,
  38. found: Arc::new(AtomicUsize::new(0)),
  39. lower_bound: 1,
  40. upper_bound: usize::max_value(),
  41. find_match: self.find_match,
  42. };
  43. self.iterator.drive(executor, consumer)
  44. }
  45. }
  46. /* FindMap */
  47. pub struct FindMap<X, O> {
  48. iterator: X,
  49. operation: O,
  50. find_match: FindMatch,
  51. }
  52. impl<X, O> FindMap<X, O> {
  53. pub fn new(iterator: X, operation: O, find_match: FindMatch) -> Self {
  54. Self {
  55. iterator,
  56. operation,
  57. find_match,
  58. }
  59. }
  60. }
  61. impl<'a, X, O, T> Driver<'a, Option<T>> for FindMap<X, O>
  62. where
  63. X: ParallelIterator<'a>,
  64. O: Fn(X::Item) -> Option<T> + Clone + Send + 'a,
  65. T: Send + 'a,
  66. {
  67. fn exec_with<E>(self, executor: E) -> E::Result
  68. where
  69. E: Executor<'a, Option<T>>,
  70. {
  71. Find::new(
  72. self.iterator.filter_map(self.operation),
  73. |_: &T| true,
  74. self.find_match,
  75. )
  76. .exec_with(executor)
  77. }
  78. }
  79. /* Any */
  80. pub struct Any<X, O> {
  81. iterator: X,
  82. operation: O,
  83. }
  84. impl<X, O> Any<X, O> {
  85. pub fn new(iterator: X, operation: O) -> Self {
  86. Self {
  87. iterator,
  88. operation,
  89. }
  90. }
  91. }
  92. impl<'a, X, O> Driver<'a, bool, Option<bool>> for Any<X, O>
  93. where
  94. X: ParallelIterator<'a>,
  95. O: Fn(X::Item) -> bool + Clone + Send + 'a,
  96. {
  97. fn exec_with<E>(self, executor: E) -> E::Result
  98. where
  99. E: Executor<'a, bool, Option<bool>>,
  100. {
  101. let executor = executor.into_inner();
  102. let ret = Find::new(
  103. self.iterator.map(self.operation),
  104. bool::clone,
  105. FindMatch::Any,
  106. )
  107. .exec_with(executor);
  108. E::map(ret, |x| x.is_some())
  109. }
  110. }
  111. /* All */
  112. pub struct All<X, O> {
  113. iterator: X,
  114. operation: O,
  115. }
  116. impl<X, O> All<X, O> {
  117. pub fn new(iterator: X, operation: O) -> Self {
  118. Self {
  119. iterator,
  120. operation,
  121. }
  122. }
  123. }
  124. impl<'a, X, O> Driver<'a, bool, Option<bool>> for All<X, O>
  125. where
  126. X: ParallelIterator<'a>,
  127. O: Fn(X::Item) -> bool + Clone + Send + 'a,
  128. {
  129. fn exec_with<E>(self, executor: E) -> E::Result
  130. where
  131. E: Executor<'a, bool, Option<bool>>,
  132. {
  133. let executor = executor.into_inner();
  134. let ret = Find::new(
  135. self.iterator.map(self.operation),
  136. |x: &bool| !x,
  137. FindMatch::Any,
  138. )
  139. .exec_with(executor);
  140. E::map(ret, |x| x.is_some())
  141. }
  142. }
  143. /* FindConsumer */
  144. struct FindConsumer<O> {
  145. operation: O,
  146. found: Arc<AtomicUsize>,
  147. lower_bound: usize,
  148. upper_bound: usize,
  149. find_match: FindMatch,
  150. }
  151. impl<O, T> Consumer<T> for FindConsumer<O>
  152. where
  153. O: Fn(&T) -> bool + Clone + Send,
  154. T: Send,
  155. {
  156. type Folder = FindFolder<O, T>;
  157. type Reducer = FindReducer;
  158. type Result = Option<T>;
  159. fn split(self) -> (Self, Self, Self::Reducer) {
  160. let FindConsumer {
  161. operation,
  162. found,
  163. lower_bound,
  164. upper_bound,
  165. find_match,
  166. } = self;
  167. let mid = lower_bound + (upper_bound - lower_bound) / 2;
  168. (
  169. Self {
  170. operation: operation.clone(),
  171. found: found.clone(),
  172. lower_bound,
  173. upper_bound: mid,
  174. find_match,
  175. },
  176. Self {
  177. operation,
  178. found,
  179. lower_bound: mid,
  180. upper_bound,
  181. find_match,
  182. },
  183. FindReducer {
  184. find_match: self.find_match,
  185. },
  186. )
  187. }
  188. fn split_at(self, _index: usize) -> (Self, Self, Self::Reducer) {
  189. self.split()
  190. }
  191. fn into_folder(self) -> Self::Folder {
  192. FindFolder {
  193. operation: self.operation,
  194. found: self.found,
  195. item: None,
  196. find_match: self.find_match,
  197. lower_bound: self.lower_bound,
  198. upper_bound: self.upper_bound,
  199. }
  200. }
  201. fn is_full(&self) -> bool {
  202. self.found.load(Ordering::Relaxed) > 0
  203. }
  204. }
  205. /* FindFolder */
  206. struct FindFolder<O, T> {
  207. operation: O,
  208. found: Arc<AtomicUsize>,
  209. item: Option<T>,
  210. lower_bound: usize,
  211. upper_bound: usize,
  212. find_match: FindMatch,
  213. }
  214. impl<O, T> Folder<T> for FindFolder<O, T>
  215. where
  216. O: Fn(&T) -> bool + Clone,
  217. {
  218. type Result = Option<T>;
  219. fn consume(mut self, item: T) -> Self {
  220. match self.find_match {
  221. FindMatch::First if self.item.is_some() => return self,
  222. FindMatch::Any if self.item.is_some() => return self,
  223. _ => (),
  224. }
  225. if (self.operation)(&item) {
  226. let mut found = self.found.load(Ordering::Relaxed);
  227. loop {
  228. let boundary = match self.find_match {
  229. FindMatch::Any if found > 0 => return self,
  230. FindMatch::First if found < self.lower_bound => return self,
  231. FindMatch::Last if found > self.upper_bound => return self,
  232. FindMatch::Any => self.lower_bound,
  233. FindMatch::First => self.lower_bound,
  234. FindMatch::Last => self.upper_bound,
  235. };
  236. let ret = self.found.compare_exchange_weak(
  237. found,
  238. boundary,
  239. Ordering::Relaxed,
  240. Ordering::Relaxed,
  241. );
  242. match ret {
  243. Ok(_) => {
  244. self.item = Some(item);
  245. break;
  246. }
  247. Err(v) => found = v,
  248. }
  249. }
  250. }
  251. self
  252. }
  253. fn complete(self) -> Self::Result {
  254. self.item
  255. }
  256. fn is_full(&self) -> bool {
  257. self.found.load(Ordering::Relaxed) > 0
  258. }
  259. }
  260. /* FindReducer */
  261. struct FindReducer {
  262. find_match: FindMatch,
  263. }
  264. impl<T> Reducer<Option<T>> for FindReducer {
  265. fn reduce(self, left: Option<T>, right: Option<T>) -> Option<T> {
  266. match self.find_match {
  267. FindMatch::First => left.or(right),
  268. FindMatch::Any => left.or(right),
  269. FindMatch::Last => right.or(left),
  270. }
  271. }
  272. }