orx_linked_list/list/consuming.rs
1use super::List;
2use crate::variant::ListVariant;
3use orx_pinned_vec::PinnedVec;
4use orx_selfref_col::{MemoryPolicy, Node};
5
6impl<V, M, P> List<V, M, P>
7where
8 V: ListVariant,
9 M: MemoryPolicy<V>,
10 P: PinnedVec<Node<V>>,
11{
12 /// Returns an arbitrary order consuming iterator of owned elements of the list.
13 ///
14 /// Note that the iterator created by `into_iter_x` is often faster than that created by `into_iter`;
15 /// and hence, can be preferred whenever the iteration order does not matter.
16 ///
17 /// # Examples
18 ///
19 /// ```rust
20 /// use orx_linked_list::*;
21 ///
22 /// let mut list = DoublyList::new();
23 ///
24 /// // a -> b -> c
25 /// list.push_front('c');
26 /// list.push_front('b');
27 /// list.push_back('x');
28 /// list.push_front('a');
29 /// list.pop_back();
30 ///
31 /// let mut vec: Vec<_> = list.into_iter_x().collect();
32 ///
33 /// // although deterministic depending on order of mutations,
34 /// // the order can be considered deterministic.
35 /// assert_eq!(vec.as_slice(), &['c', 'b', 'a']);
36 ///
37 /// vec.sort();
38 /// assert_eq!(vec.as_slice(), &['a', 'b', 'c']);
39 /// ```
40 pub fn into_iter_x(self) -> impl Iterator<Item = V::Item> {
41 let (nodes, _, _) = self.0.into_inner().0.into_inner();
42 nodes.into_iter().filter_map(|x| x.into_data())
43 }
44
45 /// Consumes the linked list and creates a parallel iterator over owned elements in **arbitrary order**.
46 ///
47 /// Note that `into_par_x` is parallel counterpart of [`into_iter_x`].
48 ///
49 /// Please see [`ParIter`] for details of the parallel computation.
50 /// In brief, computation is defined as chain of iterator transformations and parallelization
51 /// is handled by the underlying parallel executor.
52 ///
53 /// Requires **orx-parallel** feature.
54 ///
55 /// [`ParIter`]: orx_parallel::ParIter
56 /// [`into_iter_x`]: crate::List::into_iter_x
57 ///
58 /// # Examples
59 ///
60 /// ```
61 /// use orx_linked_list::*;
62 ///
63 /// let new_list = || DoublyList::from_iter(0..1024);
64 ///
65 /// let expected: usize = new_list().iter_x().sum();
66 ///
67 /// let sum = new_list().into_par_x().sum(); // parallelized computation
68 /// assert_eq!(expected, sum);
69 ///
70 /// let sum = new_list().into_par_x().num_threads(4).sum(); // using at most 4 threads
71 /// assert_eq!(expected, sum);
72 ///
73 /// let sum_doubles = new_list().into_par_x().map(|x| x * 2).sum();
74 /// assert_eq!(2 * expected, sum_doubles);
75 ///
76 /// let expected: usize = new_list().into_iter_x().filter(|x| x % 2 == 0).sum();
77 /// let sum_evens = new_list().into_par_x().filter(|x| x % 2 == 0).sum();
78 /// ```
79 #[cfg(feature = "orx-parallel")]
80 pub fn into_par_x(self) -> impl orx_parallel::ParIter<Item = V::Item>
81 where
82 V::Item: Send + Sync + Clone,
83 Node<V>: Send + Sync,
84 P: orx_concurrent_iter::IntoConcurrentIter<Item = Node<V>>,
85 {
86 use orx_parallel::*;
87 let (pinned, _, _) = self.0.into_inner().0.into_inner();
88 pinned.into_par().filter_map(|x| x.into_data())
89 }
90}