]> git.proxmox.com Git - rustc.git/blobdiff - vendor/tracing-core/src/dispatcher.rs
New upstream version 1.48.0~beta.8+dfsg1
[rustc.git] / vendor / tracing-core / src / dispatcher.rs
index 9a6048bc1ba8b0f33d93f70c4827b0bebda6f841..658463584ef14e785c77ce0f3b6dffda1c0ba78e 100644 (file)
@@ -149,7 +149,7 @@ use crate::stdlib::{
 
 #[cfg(feature = "std")]
 use crate::stdlib::{
-    cell::{Cell, RefCell},
+    cell::{Cell, RefCell, RefMut},
     error,
 };
 
@@ -193,6 +193,12 @@ struct State {
     can_enter: Cell<bool>,
 }
 
+/// While this guard is active, additional calls to subscriber functions on
+/// the default dispatcher will not be able to access the dispatch context.
+/// Dropping the guard will allow the dispatch context to be re-entered.
+#[cfg(feature = "std")]
+struct Entered<'a>(&'a State);
+
 /// A guard that resets the current default dispatcher to the prior
 /// default dispatcher when dropped.
 #[cfg(feature = "std")]
@@ -325,38 +331,46 @@ pub fn get_default<T, F>(mut f: F) -> T
 where
     F: FnMut(&Dispatch) -> T,
 {
-    // While this guard is active, additional calls to subscriber functions on
-    // the default dispatcher will not be able to access the dispatch context.
-    // Dropping the guard will allow the dispatch context to be re-entered.
-    struct Entered<'a>(&'a Cell<bool>);
-    impl<'a> Drop for Entered<'a> {
-        #[inline]
-        fn drop(&mut self) {
-            self.0.set(true);
-        }
-    }
-
     CURRENT_STATE
         .try_with(|state| {
-            if state.can_enter.replace(false) {
-                let _guard = Entered(&state.can_enter);
-
-                let mut default = state.default.borrow_mut();
-
-                if default.is::<NoSubscriber>() {
-                    if let Some(global) = get_global() {
-                        // don't redo this call on the next check
-                        *default = global.clone();
-                    }
-                }
-                f(&*default)
-            } else {
-                f(&Dispatch::none())
+            if let Some(entered) = state.enter() {
+                return f(&*entered.current());
             }
+
+            f(&Dispatch::none())
         })
         .unwrap_or_else(|_| f(&Dispatch::none()))
 }
 
+/// Executes a closure with a reference to this thread's current [dispatcher].
+///
+/// Note that calls to `get_default` should not be nested; if this function is
+/// called while inside of another `get_default`, that closure will be provided
+/// with `Dispatch::none` rather than the previously set dispatcher.
+///
+/// [dispatcher]: ../dispatcher/struct.Dispatch.html
+#[cfg(feature = "std")]
+#[doc(hidden)]
+#[inline(never)]
+pub fn get_current<T>(f: impl FnOnce(&Dispatch) -> T) -> Option<T> {
+    CURRENT_STATE
+        .try_with(|state| {
+            let entered = state.enter()?;
+            Some(f(&*entered.current()))
+        })
+        .ok()?
+}
+
+/// Executes a closure with a reference to the current [dispatcher].
+///
+/// [dispatcher]: ../dispatcher/struct.Dispatch.html
+#[cfg(not(feature = "std"))]
+#[doc(hidden)]
+pub fn get_current<T>(f: impl FnOnce(&Dispatch) -> T) -> Option<T> {
+    let dispatch = get_global()?;
+    Some(f(&dispatch))
+}
+
 /// Executes a closure with a reference to the current [dispatcher].
 ///
 /// [dispatcher]: ../dispatcher/struct.Dispatch.html
@@ -711,6 +725,42 @@ impl State {
         EXISTS.store(true, Ordering::Release);
         DefaultGuard(prior)
     }
+
+    #[inline]
+    fn enter(&self) -> Option<Entered<'_>> {
+        if self.can_enter.replace(false) {
+            Some(Entered(&self))
+        } else {
+            None
+        }
+    }
+}
+
+// ===== impl Entered =====
+
+#[cfg(feature = "std")]
+impl<'a> Entered<'a> {
+    #[inline]
+    fn current(&self) -> RefMut<'a, Dispatch> {
+        let mut default = self.0.default.borrow_mut();
+
+        if default.is::<NoSubscriber>() {
+            if let Some(global) = get_global() {
+                // don't redo this call on the next check
+                *default = global.clone();
+            }
+        }
+
+        default
+    }
+}
+
+#[cfg(feature = "std")]
+impl<'a> Drop for Entered<'a> {
+    #[inline]
+    fn drop(&mut self) {
+        self.0.can_enter.set(true);
+    }
 }
 
 // ===== impl DefaultGuard =====