mirror of
https://github.com/tokio-rs/tracing.git
synced 2025-10-01 15:00:33 +00:00
core: remove vendored lazy_static
on no-std (#2173)
Currently, `no_std` targets use a vendored version of `lazy_static` that uses the `spin` crate's `Once` type, while the `std` target uses the `once_cell` crate's `Lazy` type. This is unfortunate, as the `lazy_static` macro has a different interface from the `Lazy` cell type. This increases the amount of code that differs based on whether or not `std` is enabled. This branch removes the vendored `lazy_static` macro and replaces it with a reimplementation of `once_cell::sync::Lazy` that uses `spin::Once` rather than `once_cell::sync::OnceCell` as the inner "once type". Now, all code can be written against a `Lazy` struct with the same interface, regardless of whether or not `std` is enabled. Signed-off-by: Eliza Weisman <eliza@buoyant.io>
This commit is contained in:
parent
67cfb5f352
commit
f7966bde76
@ -111,6 +111,7 @@ use crate::stdlib::{
|
||||
};
|
||||
use crate::{
|
||||
dispatcher::Dispatch,
|
||||
lazy::Lazy,
|
||||
metadata::{LevelFilter, Metadata},
|
||||
subscriber::Interest,
|
||||
};
|
||||
@ -253,14 +254,7 @@ static CALLSITES: Callsites = Callsites {
|
||||
|
||||
static DISPATCHERS: Dispatchers = Dispatchers::new();
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
static LOCKED_CALLSITES: once_cell::sync::Lazy<Mutex<Vec<&'static dyn Callsite>>> =
|
||||
once_cell::sync::Lazy::new(Default::default);
|
||||
|
||||
#[cfg(not(feature = "std"))]
|
||||
crate::lazy_static! {
|
||||
static ref LOCKED_CALLSITES: Mutex<Vec<&'static dyn Callsite>> = Mutex::new(Vec::new());
|
||||
}
|
||||
static LOCKED_CALLSITES: Lazy<Mutex<Vec<&'static dyn Callsite>>> = Lazy::new(Default::default);
|
||||
|
||||
struct Callsites {
|
||||
list_head: AtomicPtr<DefaultCallsite>,
|
||||
@ -514,8 +508,7 @@ mod private {
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
mod dispatchers {
|
||||
use crate::dispatcher;
|
||||
use once_cell::sync::Lazy;
|
||||
use crate::{dispatcher, lazy::Lazy};
|
||||
use std::sync::{
|
||||
atomic::{AtomicBool, Ordering},
|
||||
RwLock, RwLockReadGuard, RwLockWriteGuard,
|
||||
|
76
tracing-core/src/lazy.rs
Normal file
76
tracing-core/src/lazy.rs
Normal file
@ -0,0 +1,76 @@
|
||||
#[cfg(feature = "std")]
|
||||
pub(crate) use once_cell::sync::Lazy;
|
||||
|
||||
#[cfg(not(feature = "std"))]
|
||||
pub(crate) use self::spin::Lazy;
|
||||
|
||||
#[cfg(not(feature = "std"))]
|
||||
mod spin {
|
||||
//! This is the `once_cell::sync::Lazy` type, but modified to use our
|
||||
//! `spin::Once` type rather than `OnceCell`. This is used to replace
|
||||
//! `once_cell::sync::Lazy` on `no-std` builds.
|
||||
use crate::spin::Once;
|
||||
use core::{cell::Cell, fmt, ops::Deref};
|
||||
|
||||
/// Re-implementation of `once_cell::sync::Lazy` on top of `spin::Once`
|
||||
/// rather than `OnceCell`.
|
||||
///
|
||||
/// This is used when the standard library is disabled.
|
||||
pub(crate) struct Lazy<T, F = fn() -> T> {
|
||||
cell: Once<T>,
|
||||
init: Cell<Option<F>>,
|
||||
}
|
||||
|
||||
impl<T: fmt::Debug, F> fmt::Debug for Lazy<T, F> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
f.debug_struct("Lazy")
|
||||
.field("cell", &self.cell)
|
||||
.field("init", &"..")
|
||||
.finish()
|
||||
}
|
||||
}
|
||||
|
||||
// We never create a `&F` from a `&Lazy<T, F>` so it is fine to not impl
|
||||
// `Sync` for `F`. We do create a `&mut Option<F>` in `force`, but this is
|
||||
// properly synchronized, so it only happens once so it also does not
|
||||
// contribute to this impl.
|
||||
unsafe impl<T, F: Send> Sync for Lazy<T, F> where Once<T>: Sync {}
|
||||
// auto-derived `Send` impl is OK.
|
||||
|
||||
impl<T, F> Lazy<T, F> {
|
||||
/// Creates a new lazy value with the given initializing function.
|
||||
pub(crate) const fn new(init: F) -> Lazy<T, F> {
|
||||
Lazy {
|
||||
cell: Once::new(),
|
||||
init: Cell::new(Some(init)),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, F: FnOnce() -> T> Lazy<T, F> {
|
||||
/// Forces the evaluation of this lazy value and returns a reference to
|
||||
/// the result.
|
||||
///
|
||||
/// This is equivalent to the `Deref` impl, but is explicit.
|
||||
pub(crate) fn force(this: &Lazy<T, F>) -> &T {
|
||||
this.cell.call_once(|| match this.init.take() {
|
||||
Some(f) => f(),
|
||||
None => panic!("Lazy instance has previously been poisoned"),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, F: FnOnce() -> T> Deref for Lazy<T, F> {
|
||||
type Target = T;
|
||||
fn deref(&self) -> &T {
|
||||
Lazy::force(self)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Default> Default for Lazy<T> {
|
||||
/// Creates a new lazy value using `Default` as the initializing function.
|
||||
fn default() -> Lazy<T> {
|
||||
Lazy::new(T::default)
|
||||
}
|
||||
}
|
||||
}
|
@ -1,26 +0,0 @@
|
||||
|
||||
Copyright (c) 2010 The Rust Project Developers
|
||||
|
||||
Permission is hereby granted, free of charge, to any
|
||||
person obtaining a copy of this software and associated
|
||||
documentation files (the "Software"), to deal in the
|
||||
Software without restriction, including without
|
||||
limitation the rights to use, copy, modify, merge,
|
||||
publish, distribute, sublicense, and/or sell copies of
|
||||
the Software, and to permit persons to whom the Software
|
||||
is furnished to do so, subject to the following
|
||||
conditions:
|
||||
|
||||
The above copyright notice and this permission notice
|
||||
shall be included in all copies or substantial portions
|
||||
of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
|
||||
ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
|
||||
TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
|
||||
PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
|
||||
SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
|
||||
IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
DEALINGS IN THE SOFTWARE.
|
@ -1,30 +0,0 @@
|
||||
// Copyright 2016 lazy-static.rs Developers
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0, <LICENSE-APACHE or
|
||||
// http://apache.org/licenses/LICENSE-2.0> or the MIT license <LICENSE-MIT or
|
||||
// http://opensource.org/licenses/MIT>, at your option. This file may not be
|
||||
// copied, modified, or distributed except according to those terms.
|
||||
|
||||
use crate::spin::Once;
|
||||
|
||||
pub(crate) struct Lazy<T: Sync>(Once<T>);
|
||||
|
||||
impl<T: Sync> Lazy<T> {
|
||||
pub(crate) const INIT: Self = Lazy(Once::INIT);
|
||||
|
||||
#[inline(always)]
|
||||
pub(crate) fn get<F>(&'static self, builder: F) -> &T
|
||||
where
|
||||
F: FnOnce() -> T,
|
||||
{
|
||||
self.0.call_once(builder)
|
||||
}
|
||||
}
|
||||
|
||||
#[macro_export]
|
||||
#[doc(hidden)]
|
||||
macro_rules! __lazy_static_create {
|
||||
($NAME:ident, $T:ty) => {
|
||||
static $NAME: $crate::lazy_static::lazy::Lazy<$T> = $crate::lazy_static::lazy::Lazy::INIT;
|
||||
};
|
||||
}
|
@ -1,89 +0,0 @@
|
||||
// Copyright 2016 lazy-static.rs Developers
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0, <LICENSE-APACHE or
|
||||
// http://apache.org/licenses/LICENSE-2.0> or the MIT license <LICENSE-MIT or
|
||||
// http://opensource.org/licenses/MIT>, at your option. This file may not be
|
||||
// copied, modified, or distributed except according to those terms.
|
||||
|
||||
/*!
|
||||
A macro for declaring lazily evaluated statics.
|
||||
Using this macro, it is possible to have `static`s that require code to be
|
||||
executed at runtime in order to be initialized.
|
||||
This includes anything requiring heap allocations, like vectors or hash maps,
|
||||
as well as anything that requires function calls to be computed.
|
||||
*/
|
||||
|
||||
#[path = "core_lazy.rs"]
|
||||
pub(crate) mod lazy;
|
||||
|
||||
#[doc(hidden)]
|
||||
pub(crate) use core::ops::Deref as __Deref;
|
||||
|
||||
#[macro_export]
|
||||
#[doc(hidden)]
|
||||
macro_rules! __lazy_static_internal {
|
||||
// optional visibility restrictions are wrapped in `()` to allow for
|
||||
// explicitly passing otherwise implicit information about private items
|
||||
($(#[$attr:meta])* ($($vis:tt)*) static ref $N:ident : $T:ty = $e:expr; $($t:tt)*) => {
|
||||
$crate::__lazy_static_internal!(@MAKE TY, $(#[$attr])*, ($($vis)*), $N);
|
||||
$crate::__lazy_static_internal!(@TAIL, $N : $T = $e);
|
||||
$crate::lazy_static!($($t)*);
|
||||
};
|
||||
(@TAIL, $N:ident : $T:ty = $e:expr) => {
|
||||
impl $crate::lazy_static::__Deref for $N {
|
||||
type Target = $T;
|
||||
fn deref(&self) -> &$T {
|
||||
#[inline(always)]
|
||||
fn __static_ref_initialize() -> $T { $e }
|
||||
|
||||
#[inline(always)]
|
||||
fn __stability() -> &'static $T {
|
||||
$crate::__lazy_static_create!(LAZY, $T);
|
||||
LAZY.get(__static_ref_initialize)
|
||||
}
|
||||
__stability()
|
||||
}
|
||||
}
|
||||
impl $crate::lazy_static::LazyStatic for $N {
|
||||
fn initialize(lazy: &Self) {
|
||||
let _ = &**lazy;
|
||||
}
|
||||
}
|
||||
};
|
||||
// `vis` is wrapped in `()` to prevent parsing ambiguity
|
||||
(@MAKE TY, $(#[$attr:meta])*, ($($vis:tt)*), $N:ident) => {
|
||||
#[allow(missing_copy_implementations)]
|
||||
#[allow(non_camel_case_types)]
|
||||
#[allow(dead_code)]
|
||||
$(#[$attr])*
|
||||
$($vis)* struct $N {__private_field: ()}
|
||||
#[doc(hidden)]
|
||||
$($vis)* static $N: $N = $N {__private_field: ()};
|
||||
};
|
||||
() => ()
|
||||
}
|
||||
|
||||
#[macro_export]
|
||||
#[doc(hidden)]
|
||||
macro_rules! lazy_static {
|
||||
($(#[$attr:meta])* static ref $N:ident : $T:ty = $e:expr; $($t:tt)*) => {
|
||||
// use `()` to explicitly forward the information about private items
|
||||
$crate::__lazy_static_internal!($(#[$attr])* () static ref $N : $T = $e; $($t)*);
|
||||
};
|
||||
($(#[$attr:meta])* pub static ref $N:ident : $T:ty = $e:expr; $($t:tt)*) => {
|
||||
$crate::__lazy_static_internal!($(#[$attr])* (pub) static ref $N : $T = $e; $($t)*);
|
||||
};
|
||||
($(#[$attr:meta])* pub ($($vis:tt)+) static ref $N:ident : $T:ty = $e:expr; $($t:tt)*) => {
|
||||
$crate::__lazy_static_internal!($(#[$attr])* (pub ($($vis)+)) static ref $N : $T = $e; $($t)*);
|
||||
};
|
||||
() => ()
|
||||
}
|
||||
|
||||
/// Support trait for enabling a few common operation on lazy static values.
|
||||
///
|
||||
/// This is implemented by each defined lazy static, and
|
||||
/// used by the free functions in this crate.
|
||||
pub(crate) trait LazyStatic {
|
||||
#[doc(hidden)]
|
||||
fn initialize(lazy: &Self);
|
||||
}
|
@ -254,10 +254,7 @@ macro_rules! metadata {
|
||||
};
|
||||
}
|
||||
|
||||
// Facade module: `no_std` uses spinlocks, `std` uses the mutexes in the standard library
|
||||
#[cfg(not(feature = "std"))]
|
||||
#[macro_use]
|
||||
mod lazy_static;
|
||||
pub(crate) mod lazy;
|
||||
|
||||
// Trimmed-down vendored version of spin 0.5.2 (0387621)
|
||||
// Dependency of no_std lazy_static, not required in a std build
|
||||
|
@ -64,11 +64,11 @@ mod no_std {
|
||||
}
|
||||
|
||||
impl<T> Mutex<T> {
|
||||
pub(crate) fn new(data: T) -> Self {
|
||||
Self {
|
||||
inner: crate::spin::Mutex::new(data),
|
||||
}
|
||||
}
|
||||
// pub(crate) fn new(data: T) -> Self {
|
||||
// Self {
|
||||
// inner: crate::spin::Mutex::new(data),
|
||||
// }
|
||||
// }
|
||||
|
||||
pub(crate) fn lock(&self) -> Result<MutexGuard<'_, T>, ()> {
|
||||
Ok(self.inner.lock())
|
||||
|
Loading…
x
Reference in New Issue
Block a user