parallel_task/accessors/
limit_queue.rs1use crate::utils::SpinWait;
3use super::read_accessor::*;
4use std::sync::{atomic::AtomicBool, Arc};
5
6pub struct LimitAccessQueue<T,State> {
7 pub val: Vec<T>,
8 write_block: AtomicBool,
9 state: State
10}
11
12#[allow(dead_code,clippy::new_ret_no_self)]
13impl<T,State> LimitAccessQueue<T,State>
14where State: Default + Clone
15{
16 pub fn new() -> (PrimaryAccessor<T,State>,SecondaryAccessor<T,State>) {
17 let arc_obj = Arc::new(Self {
18 val: Vec::new(),
19 write_block: AtomicBool::new(false),
20 state: State::default()
21 });
22
23 let primary = ReadAccessor::new(arc_obj.clone(),ReadAccessorType::Primary);
26 let secondary = ReadAccessor::new(arc_obj,ReadAccessorType::Secondary);
27 (PrimaryAccessor::new(primary), SecondaryAccessor::new(secondary))
28
29
30 }
31
32 pub fn set_state(&mut self, state:State) {
33 self.with_write_block(|s|{
34 s.state = state;
35 });
36 }
37
38 pub fn get_state(&mut self) -> State {
39 self.with_write_block(|s|{
40 s.state.clone()
41 })
42 }
43
44 pub fn pop(&mut self) -> Option<T> {
45 self.with_write_block(|s| {
46 s.val.pop()
47 })
48 }
49
50 pub fn pop_count(&mut self,count:usize) -> Option<Vec<T>> {
51 self.with_write_block(|s| {
52 let mut res = Vec::new();
53 for idx in 0..count {
54 if let Some(val) = s.val.pop() {
55 res.push(val)
56 } else {
57 if idx == 0 {
58 return None;
59 }
60 break;
61 }
62 }
63 Some(res)
64 })
65 }
66
67 pub fn steal(&mut self) -> Option<Vec<T>> {
80 self.with_write_block(|s| {
81 if s.val.is_empty() {
82 None
83 } else {
84 let mut tmp:Vec<T> = Vec::with_capacity(1);
86 std::mem::swap(&mut tmp, &mut s.val);
87 Some(tmp)
88 }
89 })
90 }
91
92 pub fn steal_half(&mut self) -> Option<Vec<T>> {
105 self.with_write_block(|s| {
106 if s.val.is_empty() {
107 None
108 }
109 else {
110 let res = s.val.split_off(s.val.len()/2);
111 Some(res)
112 }
113 })
114 }
115
116 pub fn is_empty(&mut self) -> bool {
117 self.len() == 0
118 }
119
120 pub fn len(&mut self) -> usize {
121 self.with_write_block(|s|{
122 if s.val.is_empty() { 0usize } else { s.val.len() }
123 })
124 }
125
126 pub fn atomic_write_block_to_true(&mut self) -> Result<bool, bool> {
127 self.write_block.compare_exchange(false, true, std::sync::atomic::Ordering::SeqCst, std::sync::atomic::Ordering::SeqCst)
128 }
129
130 pub fn with_write_block<F,Output>(&mut self, f:F) -> Output
131 where F: FnOnce(&mut Self) -> Output {
132 SpinWait::loop_while_mut(||self.atomic_write_block_to_true().is_err());
133 let output = f(self);
134 self.write_block.store(false, std::sync::atomic::Ordering::SeqCst);
135 output
136 }
137
138 pub fn push(&mut self, value:T) {
139
140 self.with_write_block(|s|
141 {
142 s.val.push(value);
143 });
144 }
145
146 pub fn write(&mut self, mut values:Vec<T>) {
147 self.with_write_block(|s|{
148 let drained = values.drain(0..);
149 s.val.extend(drained);
150 });
151 }
152
153 pub fn replace(&mut self, mut values:Vec<T>) {
154 self.with_write_block(|s|{
155 std::mem::swap(&mut values, &mut s.val);
156 });
157 }
158
159 pub fn is_write_blocked(&self) -> bool {
160 self.write_block.load(std::sync::atomic::Ordering::SeqCst)
161 }
162
163 }