Skip to content

Commit f4d443d

Browse files
committed
wip nostd without alloc
1 parent e28141b commit f4d443d

File tree

3 files changed

+230
-111
lines changed

3 files changed

+230
-111
lines changed

tracing-core/src/callsite.rs

Lines changed: 167 additions & 100 deletions
Original file line numberDiff line numberDiff line change
@@ -14,21 +14,8 @@ use core::{
1414
sync::atomic::{AtomicPtr, Ordering},
1515
};
1616

17-
lazy_static! {
18-
static ref REGISTRY: Registry = Registry {
19-
callsites: LinkedList::new(),
20-
dispatchers: Mutex::new(Vec::new()),
21-
};
22-
}
23-
24-
type Dispatchers = Vec<dispatcher::Registrar>;
2517
type Callsites = LinkedList;
2618

27-
struct Registry {
28-
callsites: Callsites,
29-
dispatchers: Mutex<Dispatchers>,
30-
}
31-
3219
/// Trait implemented by callsites.
3320
///
3421
/// These functions are only intended to be called by the callsite registry, which
@@ -76,98 +63,176 @@ pub struct Registration<T = &'static dyn Callsite> {
7663
next: AtomicPtr<Registration<T>>,
7764
}
7865

79-
/// Clear and reregister interest on every [`Callsite`]
80-
///
81-
/// This function is intended for runtime reconfiguration of filters on traces
82-
/// when the filter recalculation is much less frequent than trace events are.
83-
/// The alternative is to have the [`Subscriber`] that supports runtime
84-
/// reconfiguration of filters always return [`Interest::sometimes()`] so that
85-
/// [`enabled`] is evaluated for every event.
86-
///
87-
/// This function will also re-compute the global maximum level as determined by
88-
/// the [`max_level_hint`] method. If a [`Subscriber`]
89-
/// implementation changes the value returned by its `max_level_hint`
90-
/// implementation at runtime, then it **must** call this function after that
91-
/// value changes, in order for the change to be reflected.
92-
///
93-
/// [`max_level_hint`]: super::subscriber::Subscriber::max_level_hint
94-
/// [`Callsite`]: super::callsite::Callsite
95-
/// [`enabled`]: super::subscriber::Subscriber::enabled
96-
/// [`Interest::sometimes()`]: super::subscriber::Interest::sometimes
97-
/// [`Subscriber`]: super::subscriber::Subscriber
98-
pub fn rebuild_interest_cache() {
99-
let mut dispatchers = REGISTRY.dispatchers.lock().unwrap();
100-
let callsites = &REGISTRY.callsites;
101-
rebuild_interest(callsites, &mut dispatchers);
102-
}
66+
#[cfg(feature = "std")]
67+
pub(crate) use self::inner::register_dispatch;
68+
pub use self::inner::{rebuild_interest_cache, register};
10369

104-
/// Register a new `Callsite` with the global registry.
105-
///
106-
/// This should be called once per callsite after the callsite has been
107-
/// constructed.
108-
pub fn register(registration: &'static Registration) {
109-
let mut dispatchers = REGISTRY.dispatchers.lock().unwrap();
110-
rebuild_callsite_interest(&mut dispatchers, registration.callsite);
111-
REGISTRY.callsites.push(registration);
112-
}
70+
#[cfg(feature = "std")]
71+
mod inner {
72+
use super::*;
73+
use std::vec::Vec;
74+
type Dispatchers = Vec<dispatcher::Registrar>;
11375

114-
pub(crate) fn register_dispatch(dispatch: &Dispatch) {
115-
let mut dispatchers = REGISTRY.dispatchers.lock().unwrap();
116-
let callsites = &REGISTRY.callsites;
76+
struct Registry {
77+
callsites: Callsites,
78+
dispatchers: Mutex<Dispatchers>,
79+
}
11780

118-
dispatchers.push(dispatch.registrar());
81+
lazy_static! {
82+
static ref REGISTRY: Registry = Registry {
83+
callsites: LinkedList::new(),
84+
dispatchers: Mutex::new(Vec::new()),
85+
};
86+
}
11987

120-
rebuild_interest(callsites, &mut dispatchers);
121-
}
88+
/// Clear and reregister interest on every [`Callsite`]
89+
///
90+
/// This function is intended for runtime reconfiguration of filters on traces
91+
/// when the filter recalculation is much less frequent than trace events are.
92+
/// The alternative is to have the [`Subscriber`] that supports runtime
93+
/// reconfiguration of filters always return [`Interest::sometimes()`] so that
94+
/// [`enabled`] is evaluated for every event.
95+
///
96+
/// This function will also re-compute the global maximum level as determined by
97+
/// the [`max_level_hint`] method. If a [`Subscriber`]
98+
/// implementation changes the value returned by its `max_level_hint`
99+
/// implementation at runtime, then it **must** call this function after that
100+
/// value changes, in order for the change to be reflected.
101+
///
102+
/// [`max_level_hint`]: super::subscriber::Subscriber::max_level_hint
103+
/// [`Callsite`]: super::callsite::Callsite
104+
/// [`enabled`]: super::subscriber::Subscriber::enabled
105+
/// [`Interest::sometimes()`]: super::subscriber::Interest::sometimes
106+
/// [`Subscriber`]: super::subscriber::Subscriber
107+
pub fn rebuild_interest_cache() {
108+
let mut dispatchers = REGISTRY.dispatchers.lock().unwrap();
109+
let callsites = &REGISTRY.callsites;
110+
rebuild_interest(callsites, &mut dispatchers);
111+
}
122112

123-
fn rebuild_callsite_interest(
124-
dispatchers: &mut MutexGuard<'_, Vec<dispatcher::Registrar>>,
125-
callsite: &'static dyn Callsite,
126-
) {
127-
let meta = callsite.metadata();
128-
129-
// Iterate over the subscribers in the registry, and — if they are
130-
// active — register the callsite with them.
131-
let mut interests = dispatchers.iter().filter_map(|registrar| {
132-
registrar
133-
.upgrade()
134-
.map(|dispatch| dispatch.register_callsite(meta))
135-
});
136-
137-
// Use the first subscriber's `Interest` as the base value.
138-
let interest = if let Some(interest) = interests.next() {
139-
// Combine all remaining `Interest`s.
140-
interests.fold(interest, Interest::and)
141-
} else {
142-
// If nobody was interested in this thing, just return `never`.
143-
Interest::never()
144-
};
145-
146-
callsite.set_interest(interest)
147-
}
113+
/// Register a new `Callsite` with the global registry.
114+
///
115+
/// This should be called once per callsite after the callsite has been
116+
/// constructed.
117+
pub fn register(registration: &'static Registration) {
118+
let mut dispatchers = REGISTRY.dispatchers.lock().unwrap();
119+
rebuild_callsite_interest(&mut dispatchers, registration.callsite);
120+
REGISTRY.callsites.push(registration);
121+
}
148122

149-
fn rebuild_interest(
150-
callsites: &Callsites,
151-
dispatchers: &mut MutexGuard<'_, Vec<dispatcher::Registrar>>,
152-
) {
153-
let mut max_level = LevelFilter::OFF;
154-
dispatchers.retain(|registrar| {
155-
if let Some(dispatch) = registrar.upgrade() {
156-
// If the subscriber did not provide a max level hint, assume
157-
// that it may enable every level.
158-
let level_hint = dispatch.max_level_hint().unwrap_or(LevelFilter::TRACE);
159-
if level_hint > max_level {
160-
max_level = level_hint;
161-
}
162-
true
123+
pub(crate) fn register_dispatch(dispatch: &Dispatch) {
124+
let mut dispatchers = REGISTRY.dispatchers.lock().unwrap();
125+
let callsites = &REGISTRY.callsites;
126+
127+
dispatchers.push(dispatch.registrar());
128+
129+
rebuild_interest(callsites, &mut dispatchers);
130+
}
131+
132+
fn rebuild_callsite_interest(
133+
dispatchers: &mut MutexGuard<'_, Vec<dispatcher::Registrar>>,
134+
callsite: &'static dyn Callsite,
135+
) {
136+
let meta = callsite.metadata();
137+
138+
// Iterate over the subscribers in the registry, and — if they are
139+
// active — register the callsite with them.
140+
let mut interests = dispatchers.iter().filter_map(|registrar| {
141+
registrar
142+
.upgrade()
143+
.map(|dispatch| dispatch.register_callsite(meta))
144+
});
145+
146+
// Use the first subscriber's `Interest` as the base value.
147+
let interest = if let Some(interest) = interests.next() {
148+
// Combine all remaining `Interest`s.
149+
interests.fold(interest, Interest::and)
163150
} else {
164-
false
165-
}
166-
});
151+
// If nobody was interested in this thing, just return `never`.
152+
Interest::never()
153+
};
167154

168-
callsites.for_each(|reg| rebuild_callsite_interest(dispatchers, reg.callsite));
155+
callsite.set_interest(interest)
156+
}
157+
158+
fn rebuild_interest(
159+
callsites: &Callsites,
160+
dispatchers: &mut MutexGuard<'_, Vec<dispatcher::Registrar>>,
161+
) {
162+
let mut max_level = LevelFilter::OFF;
163+
dispatchers.retain(|registrar| {
164+
if let Some(dispatch) = registrar.upgrade() {
165+
// If the subscriber did not provide a max level hint, assume
166+
// that it may enable every level.
167+
let level_hint = dispatch.max_level_hint().unwrap_or(LevelFilter::TRACE);
168+
if level_hint > max_level {
169+
max_level = level_hint;
170+
}
171+
true
172+
} else {
173+
false
174+
}
175+
});
169176

170-
LevelFilter::set_max(max_level);
177+
callsites.for_each(|reg| rebuild_callsite_interest(dispatchers, reg.callsite));
178+
179+
LevelFilter::set_max(max_level);
180+
}
181+
}
182+
183+
#[cfg(not(feature = "std"))]
184+
mod inner {
185+
use super::*;
186+
static REGISTRY: Callsites = LinkedList::new();
187+
188+
/// Clear and reregister interest on every [`Callsite`]
189+
///
190+
/// This function is intended for runtime reconfiguration of filters on traces
191+
/// when the filter recalculation is much less frequent than trace events are.
192+
/// The alternative is to have the [`Subscriber`] that supports runtime
193+
/// reconfiguration of filters always return [`Interest::sometimes()`] so that
194+
/// [`enabled`] is evaluated for every event.
195+
///
196+
/// This function will also re-compute the global maximum level as determined by
197+
/// the [`max_level_hint`] method. If a [`Subscriber`]
198+
/// implementation changes the value returned by its `max_level_hint`
199+
/// implementation at runtime, then it **must** call this function after that
200+
/// value changes, in order for the change to be reflected.
201+
///
202+
/// [`max_level_hint`]: super::subscriber::Subscriber::max_level_hint
203+
/// [`Callsite`]: super::callsite::Callsite
204+
/// [`enabled`]: super::subscriber::Subscriber::enabled
205+
/// [`Interest::sometimes()`]: super::subscriber::Interest::sometimes
206+
/// [`Subscriber`]: super::subscriber::Subscriber
207+
pub fn rebuild_interest_cache() {
208+
rebuild_interest(&REGISTRY, crate::dispatcher::get_global());
209+
}
210+
211+
/// Register a new `Callsite` with the global registry.
212+
///
213+
/// This should be called once per callsite after the callsite has been
214+
/// constructed.
215+
pub fn register(registration: &'static Registration) {
216+
rebuild_callsite_interest(crate::dispatcher::get_global(), registration.callsite);
217+
REGISTRY.push(registration);
218+
}
219+
220+
fn rebuild_callsite_interest(dispatcher: &'static Dispatch, callsite: &'static dyn Callsite) {
221+
let meta = callsite.metadata();
222+
223+
callsite.set_interest(dispatcher.register_callsite(meta))
224+
}
225+
226+
fn rebuild_interest(callsites: &Callsites, dispatcher: &dyn Subscriber) {
227+
let mut max_level = LevelFilter::OFF;
228+
// If the subscriber did not provide a max level hint, assume
229+
// that it may enable every level.
230+
let level_hint = dispatcher.max_level_hint().unwrap_or(LevelFilter::TRACE);
231+
232+
callsites.for_each(|reg| rebuild_callsite_interest(dispatcher, reg.callsite));
233+
234+
LevelFilter::set_max(max_level);
235+
}
171236
}
172237

173238
// ===== impl Identifier =====
@@ -222,17 +287,19 @@ impl fmt::Debug for Registration {
222287
// ===== impl LinkedList =====
223288

224289
/// An intrusive atomic push-only linked list.
225-
struct LinkedList {
226-
head: AtomicPtr<Registration>,
290+
struct LinkedList<T = &'static dyn Callsite> {
291+
head: AtomicPtr<Registration<T>>,
227292
}
228293

229-
impl LinkedList {
230-
fn new() -> Self {
294+
impl<T> LinkedList<T> {
295+
const fn new() -> Self {
231296
LinkedList {
232297
head: AtomicPtr::new(ptr::null_mut()),
233298
}
234299
}
300+
}
235301

302+
impl LinkedList {
236303
fn for_each(&self, mut f: impl FnMut(&'static Registration)) {
237304
let mut head = self.head.load(Ordering::Acquire);
238305

0 commit comments

Comments
 (0)