68
68
//! # let my_dispatch = dispatcher::Dispatch::new(my_subscriber);
69
69
//! // no default subscriber
70
70
//!
71
+ //! # #[cfg(feature = "std")]
71
72
//! dispatcher::with_default(&my_dispatch, || {
72
73
//! // my_subscriber is the default
73
74
//! });
113
114
//! # }
114
115
//! ```
115
116
//!
117
+ //! **Note**: the thread-local scoped dispatcher (`with_default`) requires the
118
+ //! Rust standard library. `no_std` users should use [`set_global_default`]
119
+ //! instead.
120
+ //!
116
121
//! Finally, `tokio` users should note that versions of `tokio` >= 0.1.22
117
122
//! support an `experimental-tracing` feature flag. When this flag is enabled,
118
123
//! the `tokio` runtime's thread pool will automatically propagate the default
@@ -138,16 +143,21 @@ use crate::{
138
143
Event , Metadata ,
139
144
} ;
140
145
141
- use std :: {
146
+ use crate :: stdlib :: {
142
147
any:: Any ,
143
- cell:: { Cell , RefCell } ,
144
- error, fmt,
148
+ fmt,
145
149
sync:: {
146
150
atomic:: { AtomicUsize , Ordering } ,
147
151
Arc , Weak ,
148
152
} ,
149
153
} ;
150
154
155
+ #[ cfg( feature = "std" ) ]
156
+ use crate :: stdlib:: {
157
+ cell:: { Cell , RefCell } ,
158
+ error,
159
+ } ;
160
+
151
161
/// `Dispatch` trace data to a [`Subscriber`].
152
162
///
153
163
/// [`Subscriber`]: ../subscriber/trait.Subscriber.html
@@ -156,6 +166,7 @@ pub struct Dispatch {
156
166
subscriber : Arc < dyn Subscriber + Send + Sync > ,
157
167
}
158
168
169
+ #[ cfg( feature = "std" ) ]
159
170
thread_local ! {
160
171
static CURRENT_STATE : State = State {
161
172
default : RefCell :: new( Dispatch :: none( ) ) ,
@@ -171,6 +182,7 @@ const INITIALIZED: usize = 2;
171
182
static mut GLOBAL_DISPATCH : Option < Dispatch > = None ;
172
183
173
184
/// The dispatch state of a thread.
185
+ #[ cfg( feature = "std" ) ]
174
186
struct State {
175
187
/// This thread's current default dispatcher.
176
188
default : RefCell < Dispatch > ,
@@ -186,16 +198,22 @@ struct State {
186
198
187
199
/// A guard that resets the current default dispatcher to the prior
188
200
/// default dispatcher when dropped.
201
+ #[ cfg( feature = "std" ) ]
189
202
struct ResetGuard ( Option < Dispatch > ) ;
190
203
191
204
/// Sets this dispatch as the default for the duration of a closure.
192
205
///
193
206
/// The default dispatcher is used when creating a new [span] or
194
207
/// [`Event`].
195
208
///
209
+ /// **Note**: This function requires the Rust standard library. `no_std` users
210
+ /// should use [`set_global_default`] instead.
211
+ ///
196
212
/// [span]: ../span/index.html
197
213
/// [`Subscriber`]: ../subscriber/trait.Subscriber.html
198
214
/// [`Event`]: ../event/struct.Event.html
215
+ /// [`set_global_default`]: ../fn.set_global_default.html
216
+ #[ cfg( feature = "std" ) ]
199
217
pub fn with_default < T > ( dispatcher : & Dispatch , f : impl FnOnce ( ) -> T ) -> T {
200
218
// When this guard is dropped, the default dispatcher will be reset to the
201
219
// prior default. Using this (rather than simply resetting after calling
@@ -243,6 +261,7 @@ impl fmt::Display for SetGlobalDefaultError {
243
261
}
244
262
}
245
263
264
+ #[ cfg( feature = "std" ) ]
246
265
impl error:: Error for SetGlobalDefaultError { }
247
266
248
267
/// Executes a closure with a reference to this thread's current [dispatcher].
@@ -252,6 +271,7 @@ impl error::Error for SetGlobalDefaultError {}
252
271
/// with `Dispatch::none` rather than the previously set dispatcher.
253
272
///
254
273
/// [dispatcher]: ../dispatcher/struct.Dispatch.html
274
+ #[ cfg( feature = "std" ) ]
255
275
pub fn get_default < T , F > ( mut f : F ) -> T
256
276
where
257
277
F : FnMut ( & Dispatch ) -> T ,
@@ -274,14 +294,10 @@ where
274
294
275
295
let mut default = state. default . borrow_mut ( ) ;
276
296
277
- if default. is :: < NoSubscriber > ( ) && GLOBAL_INIT . load ( Ordering :: SeqCst ) == INITIALIZED
278
- {
279
- // don't redo this call on the next check
280
- unsafe {
281
- * default = GLOBAL_DISPATCH
282
- . as_ref ( )
283
- . expect ( "invariant violated: GLOBAL_DISPATCH must be initialized before GLOBAL_INIT is set" )
284
- . clone ( )
297
+ if default. is :: < NoSubscriber > ( ) {
298
+ if let Some ( global) = get_global ( ) {
299
+ // don't redo this call on the next check
300
+ * default = global. clone ( ) ;
285
301
}
286
302
}
287
303
f ( & * default)
@@ -292,6 +308,34 @@ where
292
308
. unwrap_or_else ( |_| f ( & Dispatch :: none ( ) ) )
293
309
}
294
310
311
+ /// Executes a closure with a reference to the current [dispatcher].
312
+ ///
313
+ /// [dispatcher]: ../dispatcher/struct.Dispatch.html
314
+ #[ cfg( not( feature = "std" ) ) ]
315
+ pub fn get_default < T , F > ( mut f : F ) -> T
316
+ where
317
+ F : FnMut ( & Dispatch ) -> T ,
318
+ {
319
+ if let Some ( d) = get_global ( ) {
320
+ f ( d)
321
+ } else {
322
+ f ( & Dispatch :: none ( ) )
323
+ }
324
+ }
325
+
326
+ fn get_global ( ) -> Option < & ' static Dispatch > {
327
+ if GLOBAL_INIT . load ( Ordering :: SeqCst ) != INITIALIZED {
328
+ return None ;
329
+ }
330
+ unsafe {
331
+ // This is safe given the invariant that setting the global dispatcher
332
+ // also sets `GLOBAL_INIT` to `INITIALIZED`.
333
+ Some ( GLOBAL_DISPATCH . as_ref ( ) . expect (
334
+ "invariant violated: GLOBAL_DISPATCH must be initialized before GLOBAL_INIT is set" ,
335
+ ) )
336
+ }
337
+ }
338
+
295
339
pub ( crate ) struct Registrar ( Weak < dyn Subscriber + Send + Sync > ) ;
296
340
297
341
impl Dispatch {
@@ -568,6 +612,7 @@ impl Registrar {
568
612
569
613
// ===== impl State =====
570
614
615
+ #[ cfg( feature = "std" ) ]
571
616
impl State {
572
617
/// Replaces the current default dispatcher on this thread with the provided
573
618
/// dispatcher.Any
@@ -588,6 +633,7 @@ impl State {
588
633
589
634
// ===== impl ResetGuard =====
590
635
636
+ #[ cfg( feature = "std" ) ]
591
637
impl Drop for ResetGuard {
592
638
#[ inline]
593
639
fn drop ( & mut self ) {
@@ -602,14 +648,15 @@ impl Drop for ResetGuard {
602
648
#[ cfg( test) ]
603
649
mod test {
604
650
use super :: * ;
651
+ #[ cfg( feature = "std" ) ]
652
+ use crate :: stdlib:: sync:: atomic:: { AtomicUsize , Ordering } ;
605
653
use crate :: {
606
654
callsite:: Callsite ,
607
655
metadata:: { Kind , Level , Metadata } ,
608
656
span,
609
657
subscriber:: { Interest , Subscriber } ,
610
658
Event ,
611
659
} ;
612
- use std:: sync:: atomic:: { AtomicUsize , Ordering } ;
613
660
614
661
#[ test]
615
662
fn dispatch_is ( ) {
@@ -642,6 +689,7 @@ mod test {
642
689
}
643
690
644
691
#[ test]
692
+ #[ cfg( feature = "std" ) ]
645
693
fn events_dont_infinite_loop ( ) {
646
694
// This test ensures that an event triggered within a subscriber
647
695
// won't cause an infinite loop of events.
@@ -680,6 +728,7 @@ mod test {
680
728
}
681
729
682
730
#[ test]
731
+ #[ cfg( feature = "std" ) ]
683
732
fn spans_dont_infinite_loop ( ) {
684
733
// This test ensures that a span created within a subscriber
685
734
// won't cause an infinite loop of new spans.
@@ -740,7 +789,10 @@ mod test {
740
789
fn enter ( & self , _: & span:: Id ) { }
741
790
fn exit ( & self , _: & span:: Id ) { }
742
791
}
792
+ #[ cfg( feature = "std" ) ]
743
793
struct TestSubscriberB ;
794
+
795
+ #[ cfg( feature = "std" ) ]
744
796
impl Subscriber for TestSubscriberB {
745
797
fn enabled ( & self , _: & Metadata < ' _ > ) -> bool {
746
798
true
@@ -765,6 +817,7 @@ mod test {
765
817
)
766
818
} ) ;
767
819
820
+ #[ cfg( feature = "std" ) ]
768
821
with_default ( & Dispatch :: new ( TestSubscriberB ) , || {
769
822
get_default ( |current| {
770
823
assert ! (
0 commit comments