1mod command;
4
5pub use self::command::*;
6use {
7 crate::frame::{Frame, Frames},
8 std::collections::VecDeque,
9};
10
11#[derive(Debug)]
14pub enum CirqueRef<'a, T, I = T, P = T> {
15 Initial(InitialRef<'a, T, I, P>),
17
18 Ready(ReadyRef<'a, T, I, P>),
20}
21
22impl<'a, T, I, P> CirqueRef<'a, T, I, P> {
23 pub fn or_init(self, init: impl FnOnce(I) -> T) -> ReadyRef<'a, T, I, P> {
25 match self {
26 CirqueRef::Initial(initial) => initial.init(init),
27 CirqueRef::Ready(ready) => ready,
28 }
29 }
30
31 pub fn or_reset(self, reset: impl FnOnce(T) -> I) -> InitialRef<'a, T, I, P> {
33 match self {
34 CirqueRef::Initial(initial) => initial,
35 CirqueRef::Ready(ready) => ready.reset(reset),
36 }
37 }
38
39 pub fn index(&self) -> usize {
41 match self {
42 CirqueRef::Initial(initial) => initial.index(),
43 CirqueRef::Ready(ready) => ready.index(),
44 }
45 }
46}
47
48#[derive(Debug)]
51pub struct InitialRef<'a, T, I = T, P = T> {
52 relevant: relevant::Relevant,
53 cirque: &'a mut Cirque<T, I, P>,
54 value: I,
55 frame: Frame,
56 index: usize,
57}
58
59impl<'a, T, I, P> InitialRef<'a, T, I, P> {
60 pub fn init(self, init: impl FnOnce(I) -> T) -> ReadyRef<'a, T, I, P> {
62 ReadyRef {
63 relevant: self.relevant,
64 cirque: self.cirque,
65 value: init(self.value),
66 frame: self.frame,
67 index: self.index,
68 }
69 }
70
71 pub fn index(&self) -> usize {
73 self.index
74 }
75}
76
77#[derive(Debug)]
80pub struct ReadyRef<'a, T, I = T, P = T> {
81 relevant: relevant::Relevant,
82 cirque: &'a mut Cirque<T, I, P>,
83 value: T,
84 frame: Frame,
85 index: usize,
86}
87
88impl<'a, T, I, P> ReadyRef<'a, T, I, P> {
89 pub fn reset(self, reset: impl FnOnce(T) -> I) -> InitialRef<'a, T, I, P> {
91 InitialRef {
92 relevant: self.relevant,
93 cirque: self.cirque,
94 value: reset(self.value),
95 frame: self.frame,
96 index: self.index,
97 }
98 }
99
100 pub fn finish(self, finish: impl FnOnce(T) -> P) {
102 self.relevant.dispose();
103 self.cirque
104 .pending
105 .push_back((finish(self.value), self.index, self.frame))
106 }
107
108 pub fn index(&self) -> usize {
110 self.index
111 }
112}
113
114#[derive(Debug)]
118pub struct Cirque<T, I = T, P = T> {
119 pending: VecDeque<(P, usize, Frame)>,
120 ready: VecDeque<(T, usize)>,
121 marker: std::marker::PhantomData<fn() -> I>,
122 counter: usize,
123}
124
125impl<T, I, P> Default for Cirque<T, I, P> {
126 fn default() -> Self {
127 Cirque {
128 pending: VecDeque::default(),
129 ready: VecDeque::default(),
130 marker: std::marker::PhantomData,
131 counter: usize::default(),
132 }
133 }
134}
135
136impl<T, I, P> Cirque<T, I, P> {
137 pub fn new() -> Self {
139 Self::default()
140 }
141
142 pub fn dispose(mut self, mut dispose: impl FnMut(either::Either<T, P>)) {
144 self.pending
145 .drain(..)
146 .for_each(|(value, _, _)| dispose(either::Right(value)));
147 self.ready
148 .drain(..)
149 .for_each(|(value, _)| dispose(either::Left(value)));
150 }
151
152 pub fn get<B: rendy_core::hal::Backend>(
155 &mut self,
156 frames: &Frames<B>,
157 alloc: impl FnOnce() -> I,
158 complete: impl Fn(P) -> T,
159 ) -> CirqueRef<'_, T, I, P> {
160 while let Some((value, index, frame)) = self.pending.pop_front() {
161 if frames.is_complete(frame) {
162 self.ready.push_back((complete(value), index));
163 } else {
164 self.pending.push_front((value, index, frame));
165 break;
166 }
167 }
168 if let Some((value, index)) = self.ready.pop_front() {
169 CirqueRef::Ready(ReadyRef {
170 relevant: relevant::Relevant,
171 cirque: self,
172 value,
173 frame: frames.next(),
174 index,
175 })
176 } else {
177 self.counter += 1;
178 let index = self.counter - 1;
179 let value = alloc();
180 CirqueRef::Initial(InitialRef {
181 relevant: relevant::Relevant,
182 index,
183 cirque: self,
184 value,
185 frame: frames.next(),
186 })
187 }
188 }
189}
190
191#[derive(Debug)]
195pub struct DependentCirque<T, I = T, P = T> {
196 values: Vec<either::Either<T, P>>,
197 marker: std::marker::PhantomData<fn() -> I>,
198}
199
200impl<T, I, P> Default for DependentCirque<T, I, P> {
201 fn default() -> Self {
202 DependentCirque {
203 values: Vec::default(),
204 marker: std::marker::PhantomData,
205 }
206 }
207}