1use std::cell::Cell;
2use std::rc::Rc;
3use std::task;
4
5use crate::task::LocalWaker;
6
7#[derive(Clone)]
8pub struct Counter(Rc<CounterInner>);
12
13struct CounterInner {
14 count: Cell<usize>,
15 capacity: usize,
16 task: LocalWaker,
17}
18
19impl Counter {
20 pub fn new(capacity: usize) -> Self {
22 Counter(Rc::new(CounterInner {
23 capacity,
24 count: Cell::new(0),
25 task: LocalWaker::new(),
26 }))
27 }
28
29 pub fn get(&self) -> CounterGuard {
31 CounterGuard::new(self.0.clone())
32 }
33
34 pub fn available(&self, cx: &mut task::Context<'_>) -> bool {
37 self.0.available(cx)
38 }
39
40 pub fn total(&self) -> usize {
42 self.0.count.get()
43 }
44}
45
46pub struct CounterGuard(Rc<CounterInner>);
47
48impl CounterGuard {
49 fn new(inner: Rc<CounterInner>) -> Self {
50 inner.inc();
51 CounterGuard(inner)
52 }
53}
54
55impl Unpin for CounterGuard {}
56
57impl Drop for CounterGuard {
58 fn drop(&mut self) {
59 self.0.dec();
60 }
61}
62
63impl CounterInner {
64 fn inc(&self) {
65 self.count.set(self.count.get() + 1);
66 }
67
68 fn dec(&self) {
69 let num = self.count.get();
70 self.count.set(num - 1);
71 if num == self.capacity {
72 self.task.wake();
73 }
74 }
75
76 fn available(&self, cx: &mut task::Context<'_>) -> bool {
77 if self.count.get() < self.capacity {
78 true
79 } else {
80 self.task.register(cx.waker());
81 false
82 }
83 }
84}