@@ -91,3 +91,66 @@ impl<T: PointerWrapper + Deref> PointerWrapper for Pin<T> {
91
91
Pin :: new_unchecked ( T :: from_pointer ( p) )
92
92
}
93
93
}
94
+
95
+ /// Runs a cleanup function/closure when dropped.
96
+ ///
97
+ /// The [`ScopeGuard::dismiss`] function prevents the cleanup function from running.
98
+ ///
99
+ /// # Examples
100
+ ///
101
+ /// In the example below, we have multiple exit paths and we want to log regardless of which one is
102
+ /// taken:
103
+ /// ```
104
+ /// fn example1(arg: bool) {
105
+ /// let _log = ScopeGuard::new(|| pr_info!("example1 completed\n"));
106
+ ///
107
+ /// if arg {
108
+ /// return;
109
+ /// }
110
+ ///
111
+ /// // Do something...
112
+ /// }
113
+ /// ```
114
+ ///
115
+ /// In the example below, we want to log the same message on all early exits but a different one on
116
+ /// the main exit path:
117
+ /// ```
118
+ /// fn example2(arg: bool) {
119
+ /// let log = ScopeGuard::new(|| pr_info!("example2 returned early\n"));
120
+ ///
121
+ /// if arg {
122
+ /// return;
123
+ /// }
124
+ ///
125
+ /// // (Other early returns...)
126
+ ///
127
+ /// log.dismiss();
128
+ /// pr_info!("example2 no early return\n");
129
+ /// }
130
+ /// ```
131
+ pub struct ScopeGuard < T : FnOnce ( ) > {
132
+ cleanup_func : Option < T > ,
133
+ }
134
+
135
+ impl < T : FnOnce ( ) > ScopeGuard < T > {
136
+ /// Creates a new cleanup object with the given cleanup function.
137
+ pub fn new ( cleanup_func : T ) -> Self {
138
+ Self {
139
+ cleanup_func : Some ( cleanup_func) ,
140
+ }
141
+ }
142
+
143
+ /// Prevents the cleanup function from running.
144
+ pub fn dismiss ( mut self ) {
145
+ self . cleanup_func . take ( ) ;
146
+ }
147
+ }
148
+
149
+ impl < T : FnOnce ( ) > Drop for ScopeGuard < T > {
150
+ fn drop ( & mut self ) {
151
+ // Run the cleanup function if one is still present.
152
+ if let Some ( cleanup) = self . cleanup_func . take ( ) {
153
+ cleanup ( ) ;
154
+ }
155
+ }
156
+ }
0 commit comments