1use core::{cell::Cell, fmt, task};
4use std::rc::Rc;
5
6use local_waker::LocalWaker;
7
8#[derive(Debug, Clone)]
12pub struct Counter(Rc<CounterInner>);
13
14impl Counter {
15 pub fn new(capacity: usize) -> Self {
17 Counter(Rc::new(CounterInner {
18 capacity,
19 count: Cell::new(0),
20 task: LocalWaker::new(),
21 }))
22 }
23
24 #[inline]
26 pub fn get(&self) -> CounterGuard {
27 CounterGuard::new(self.0.clone())
28 }
29
30 #[inline]
32 pub fn available(&self, cx: &mut task::Context<'_>) -> bool {
33 self.0.available(cx)
34 }
35
36 #[inline]
38 pub fn total(&self) -> usize {
39 self.0.count.get()
40 }
41}
42
43struct CounterInner {
44 count: Cell<usize>,
45 capacity: usize,
46 task: LocalWaker,
47}
48
49impl CounterInner {
50 fn inc(&self) {
51 self.count.set(self.count.get() + 1);
52 }
53
54 fn dec(&self) {
55 let num = self.count.get();
56 self.count.set(num - 1);
57 if num == self.capacity {
58 self.task.wake();
59 }
60 }
61
62 fn available(&self, cx: &mut task::Context<'_>) -> bool {
63 if self.count.get() < self.capacity {
64 true
65 } else {
66 self.task.register(cx.waker());
67 false
68 }
69 }
70}
71
72impl fmt::Debug for CounterInner {
73 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
74 f.debug_struct("Counter")
75 .field("count", &self.count.get())
76 .field("capacity", &self.capacity)
77 .field("task", &self.task)
78 .finish()
79 }
80}
81
82#[derive(Debug)]
84pub struct CounterGuard(Rc<CounterInner>);
85
86impl CounterGuard {
87 fn new(inner: Rc<CounterInner>) -> Self {
88 inner.inc();
89 CounterGuard(inner)
90 }
91}
92
93impl Unpin for CounterGuard {}
94
95impl Drop for CounterGuard {
96 fn drop(&mut self) {
97 self.0.dec();
98 }
99}