1#[must_use = "if unused the deferred action will execute immediately"]
9pub struct Deferred<F: FnOnce()> {
10 action: Option<F>,
11}
12
13impl<F: FnOnce()> Deferred<F> {
14 #[inline]
16 pub const fn new(action: F) -> Self {
17 Self { action: Some(action) }
18 }
19
20 #[inline]
22 pub fn cancel(&mut self) {
23 self.action = None;
24 }
25
26 #[inline]
28 pub fn call(&mut self) {
29 if let Some(action) = self.action.take() {
30 action();
31 }
32 }
33}
34
35impl<F: FnOnce()> Drop for Deferred<F> {
36 #[inline]
37 fn drop(&mut self) {
38 if let Some(action) = self.action.take() {
39 action();
40 }
41 }
42}
43
44#[inline]
49pub fn defer<F: FnOnce()>(action: F) -> Deferred<F> {
50 Deferred::new(action)
51}
52
53#[cfg(test)]
54mod tests {
55 use super::*;
56 use core::cell::Cell;
57
58 #[test]
59 fn test_defer_runs_on_drop() {
60 let executed = Cell::new(false);
61 {
62 let _guard = defer(|| {
63 executed.set(true);
64 });
65 assert!(!executed.get());
66 }
67 assert!(executed.get());
68 }
69
70 #[test]
71 fn test_defer_cancel() {
72 let executed = Cell::new(false);
73 {
74 let mut guard = defer(|| {
75 executed.set(true);
76 });
77 guard.cancel();
78 }
79 assert!(!executed.get());
80 }
81
82 #[test]
83 fn test_defer_call_early() {
84 let count = Cell::new(0);
85 {
86 let mut guard = defer(|| {
87 count.set(count.get() + 1);
88 });
89 assert_eq!(count.get(), 0);
90 guard.call();
91 assert_eq!(count.get(), 1);
92 }
93 assert_eq!(count.get(), 1);
95 }
96}