@@ -19,41 +19,75 @@ use std::cell::RefCell;
19
19
const RED_ZONE : usize = 128 * 1024 ; // 128KiB
20
20
const STACK_SIZE : usize = 16 * RED_ZONE ; // 2MiB
21
21
22
+ /// Recursion depth.
23
+ struct Depth {
24
+ /// The current depth.
25
+ current : usize ,
26
+ /// The max depth reached so far, not considering the current depth.
27
+ last_max : usize ,
28
+ }
29
+
30
+ impl Depth {
31
+ const fn new ( ) -> Self {
32
+ Self {
33
+ current : 0 ,
34
+ last_max : 0 ,
35
+ }
36
+ }
37
+
38
+ fn reset ( & mut self ) {
39
+ * self = Self :: new ( ) ;
40
+ }
41
+ }
42
+
22
43
/// The tracker for a recursive function.
23
44
pub struct Tracker {
24
- depth : RefCell < usize > ,
45
+ depth : RefCell < Depth > ,
25
46
}
26
47
27
48
impl Tracker {
28
49
/// Create a new tracker.
29
50
pub const fn new ( ) -> Self {
30
51
Self {
31
- depth : RefCell :: new ( 0 ) ,
52
+ depth : RefCell :: new ( Depth :: new ( ) ) ,
32
53
}
33
54
}
34
55
35
56
/// Retrieve the current depth of the recursion. Starts from 1 once the
36
57
/// recursive function is called.
37
58
pub fn depth ( & self ) -> usize {
38
- * self . depth . borrow ( )
59
+ self . depth . borrow ( ) . current
60
+ }
61
+
62
+ /// Check if the current depth reaches the given depth **for the first time**.
63
+ ///
64
+ /// This is useful for logging without any duplication.
65
+ pub fn depth_reaches ( & self , depth : usize ) -> bool {
66
+ let d = self . depth . borrow ( ) ;
67
+ d. current == depth && d. current > d. last_max
39
68
}
40
69
41
70
/// Run a recursive function. Grow the stack if necessary.
42
71
fn recurse < T > ( & self , f : impl FnOnce ( ) -> T ) -> T {
43
72
struct DepthGuard < ' a > {
44
- depth : & ' a RefCell < usize > ,
73
+ depth : & ' a RefCell < Depth > ,
45
74
}
46
75
47
76
impl < ' a > DepthGuard < ' a > {
48
- fn new ( depth : & ' a RefCell < usize > ) -> Self {
49
- * depth. borrow_mut ( ) += 1 ;
77
+ fn new ( depth : & ' a RefCell < Depth > ) -> Self {
78
+ depth. borrow_mut ( ) . current += 1 ;
50
79
Self { depth }
51
80
}
52
81
}
53
82
54
83
impl < ' a > Drop for DepthGuard < ' a > {
55
84
fn drop ( & mut self ) {
56
- * self . depth . borrow_mut ( ) -= 1 ;
85
+ let mut d = self . depth . borrow_mut ( ) ;
86
+ d. last_max = d. last_max . max ( d. current ) ; // update the last max depth
87
+ d. current -= 1 ; // restore the current depth
88
+ if d. current == 0 {
89
+ d. reset ( ) ; // reset state if the recursion is finished
90
+ }
57
91
}
58
92
}
59
93
0 commit comments