mcp_usage_tower/
deferred.rs1use std::collections::VecDeque;
25use std::future::Future;
26use std::pin::Pin;
27use std::sync::Mutex;
28use std::sync::atomic::{AtomicU64, Ordering};
29
30type Parked = Pin<Box<dyn Future<Output = ()> + Send>>;
32
33pub struct DeferredCompletions {
39 queue: Mutex<VecDeque<Parked>>,
40 capacity: usize,
41 dropped: AtomicU64,
42}
43
44impl std::fmt::Debug for DeferredCompletions {
45 fn fmt(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
46 formatter
47 .debug_struct("DeferredCompletions")
48 .field("pending", &self.len())
49 .field("capacity", &self.capacity)
50 .field("dropped", &self.dropped.load(Ordering::Relaxed))
51 .finish_non_exhaustive()
52 }
53}
54
55impl DeferredCompletions {
56 pub(crate) fn new(capacity: usize) -> Self {
57 Self {
58 queue: Mutex::new(VecDeque::new()),
59 capacity,
60 dropped: AtomicU64::new(0),
61 }
62 }
63
64 pub(crate) fn park(&self, completion: Parked) -> bool {
71 let mut queue = self
72 .queue
73 .lock()
74 .unwrap_or_else(std::sync::PoisonError::into_inner);
75 if self.capacity == 0 {
76 self.record_drop();
77 return false;
78 }
79 let mut evicted = false;
80 while queue.len() >= self.capacity {
81 queue.pop_front();
82 evicted = true;
83 }
84 queue.push_back(completion);
85 if evicted {
86 self.record_drop();
87 }
88 !evicted
89 }
90
91 fn take_one(&self) -> Option<Parked> {
92 self.queue
93 .lock()
94 .unwrap_or_else(std::sync::PoisonError::into_inner)
95 .pop_front()
96 }
97
98 fn requeue_in_flight(&self, completion: Parked) {
99 let mut queue = self
100 .queue
101 .lock()
102 .unwrap_or_else(std::sync::PoisonError::into_inner);
103 if self.capacity == 0 {
104 self.record_drop();
105 return;
106 }
107 if queue.len() >= self.capacity {
108 queue.pop_back();
109 self.record_drop();
110 }
111 queue.push_front(completion);
112 }
113
114 fn record_drop(&self) {
115 let mut current = self.dropped.load(Ordering::Relaxed);
116 loop {
117 let next = current.saturating_add(1);
118 if next == current {
119 return;
120 }
121 match self.dropped.compare_exchange_weak(
122 current,
123 next,
124 Ordering::Relaxed,
125 Ordering::Relaxed,
126 ) {
127 Ok(_) => return,
128 Err(observed) => current = observed,
129 }
130 }
131 }
132
133 pub async fn drain_some(&self, limit: usize) -> usize {
139 let mut completed = 0;
140 while completed < limit {
141 let Some(completion) = self.take_one() else {
142 break;
143 };
144 InFlight::new(self, completion).run().await;
145 completed += 1;
146 }
147 completed
148 }
149
150 pub async fn drain(&self) -> usize {
156 let mut total = 0;
157 loop {
158 let ran = self.drain_some(self.capacity.max(1)).await;
159 if ran == 0 {
160 return total;
161 }
162 total = total.saturating_add(ran);
163 }
164 }
165
166 #[must_use]
168 pub fn len(&self) -> usize {
169 self.queue
170 .lock()
171 .unwrap_or_else(std::sync::PoisonError::into_inner)
172 .len()
173 }
174
175 #[must_use]
177 pub fn is_empty(&self) -> bool {
178 self.len() == 0
179 }
180
181 #[must_use]
186 pub fn dropped(&self) -> u64 {
187 self.dropped.load(Ordering::Relaxed)
188 }
189}
190
191struct InFlight<'a> {
192 deferred: &'a DeferredCompletions,
193 completion: Option<Parked>,
194}
195
196impl<'a> InFlight<'a> {
197 fn new(deferred: &'a DeferredCompletions, completion: Parked) -> Self {
198 Self {
199 deferred,
200 completion: Some(completion),
201 }
202 }
203
204 async fn run(mut self) {
205 if let Some(completion) = self.completion.as_mut() {
206 completion.as_mut().await;
207 }
208 self.completion = None;
209 }
210}
211
212impl Drop for InFlight<'_> {
213 fn drop(&mut self) {
214 if let Some(completion) = self.completion.take() {
215 if std::thread::panicking() {
216 self.deferred.record_drop();
217 } else {
218 self.deferred.requeue_in_flight(completion);
219 }
220 }
221 }
222}
223
224#[cfg(test)]
225mod tests {
226 use super::*;
227 use std::sync::Arc;
228 use std::sync::atomic::AtomicUsize;
229
230 struct PendingUntilAllowed {
231 polls: Arc<AtomicUsize>,
232 allowed: Arc<std::sync::atomic::AtomicBool>,
233 }
234
235 impl Future for PendingUntilAllowed {
236 type Output = ();
237
238 fn poll(
239 self: Pin<&mut Self>,
240 _context: &mut std::task::Context<'_>,
241 ) -> std::task::Poll<()> {
242 self.polls.fetch_add(1, Ordering::Relaxed);
243 if self.allowed.load(Ordering::Relaxed) {
244 std::task::Poll::Ready(())
245 } else {
246 std::task::Poll::Pending
247 }
248 }
249 }
250
251 fn counting(counter: &Arc<AtomicUsize>) -> Parked {
252 let counter = Arc::clone(counter);
253 Box::pin(async move {
254 counter.fetch_add(1, Ordering::Relaxed);
255 })
256 }
257
258 #[tokio::test]
259 async fn parked_completions_run_when_drained() {
260 let ran = Arc::new(AtomicUsize::new(0));
261 let deferred = DeferredCompletions::new(8);
262 for _ in 0..3 {
263 assert!(deferred.park(counting(&ran)));
264 }
265 assert_eq!(deferred.len(), 3);
266
267 assert_eq!(deferred.drain().await, 3);
268 assert_eq!(ran.load(Ordering::Relaxed), 3);
269 assert!(deferred.is_empty());
270 assert_eq!(deferred.dropped(), 0);
271 }
272
273 #[tokio::test]
274 async fn draining_is_bounded_by_the_limit() {
275 let ran = Arc::new(AtomicUsize::new(0));
276 let deferred = DeferredCompletions::new(8);
277 for _ in 0..5 {
278 deferred.park(counting(&ran));
279 }
280
281 assert_eq!(deferred.drain_some(2).await, 2);
282 assert_eq!(ran.load(Ordering::Relaxed), 2);
283 assert_eq!(deferred.len(), 3, "the rest must stay queued");
284 }
285
286 #[tokio::test]
287 async fn a_full_queue_evicts_the_oldest_and_reports_the_loss() {
288 let ran = Arc::new(AtomicUsize::new(0));
289 let deferred = DeferredCompletions::new(2);
290 assert!(deferred.park(counting(&ran)));
291 assert!(deferred.park(counting(&ran)));
292 assert!(
293 !deferred.park(counting(&ran)),
294 "the third must report that something was discarded"
295 );
296
297 assert_eq!(deferred.len(), 2, "the queue must stay bounded");
298 assert_eq!(deferred.dropped(), 1);
299 assert_eq!(deferred.drain().await, 2);
300 }
301
302 #[tokio::test]
303 async fn a_zero_capacity_queue_accepts_nothing() {
304 let ran = Arc::new(AtomicUsize::new(0));
305 let deferred = DeferredCompletions::new(0);
306 assert!(!deferred.park(counting(&ran)));
307 assert!(deferred.is_empty());
308 assert_eq!(deferred.dropped(), 1);
309 assert_eq!(deferred.drain().await, 0);
310 assert_eq!(ran.load(Ordering::Relaxed), 0);
311 }
312
313 #[tokio::test]
314 async fn draining_an_empty_queue_is_a_no_op() {
315 let deferred = DeferredCompletions::new(4);
316 assert_eq!(deferred.drain().await, 0);
317 assert_eq!(deferred.drain_some(10).await, 0);
318 }
319
320 #[tokio::test]
321 async fn cancelling_a_drain_requeues_the_in_flight_completion() {
322 let deferred = Arc::new(DeferredCompletions::new(4));
323 let polls = Arc::new(AtomicUsize::new(0));
324 let allowed = Arc::new(std::sync::atomic::AtomicBool::new(false));
325 assert!(deferred.park(Box::pin(PendingUntilAllowed {
326 polls: Arc::clone(&polls),
327 allowed: Arc::clone(&allowed),
328 })));
329
330 let drain = tokio::spawn({
331 let deferred = Arc::clone(&deferred);
332 async move { deferred.drain_some(1).await }
333 });
334 while polls.load(Ordering::Relaxed) == 0 {
335 tokio::task::yield_now().await;
336 }
337 drain.abort();
338 assert!(drain.await.unwrap_err().is_cancelled());
339 assert_eq!(deferred.len(), 1);
340
341 allowed.store(true, Ordering::Relaxed);
342 assert_eq!(deferred.drain_some(1).await, 1);
343 assert!(deferred.is_empty());
344 assert_eq!(deferred.dropped(), 0);
345 }
346}