@@ -91,3 +91,66 @@ impl<T: PointerWrapper + Deref> PointerWrapper for Pin<T> {
9191 Pin :: new_unchecked ( T :: from_pointer ( p) )
9292 }
9393}
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