From 2084fc6b40aa8eb6052ef1ef80569f7d3f6be4bb Mon Sep 17 00:00:00 2001 From: Asuna Date: Mon, 19 Aug 2024 04:16:28 +0800 Subject: [PATCH] 1 --- spdlog/benches/spdlog-rs/pattern.rs | 10 +- spdlog/src/formatter/full_formatter.rs | 9 +- spdlog/src/formatter/local_time_cacher.rs | 69 +++-- spdlog/src/formatter/mod.rs | 11 +- spdlog/src/formatter/pattern_formatter/mod.rs | 31 ++- .../pattern_formatter/pattern/datetime.rs | 238 +++++++----------- 6 files changed, 183 insertions(+), 185 deletions(-) diff --git a/spdlog/benches/spdlog-rs/pattern.rs b/spdlog/benches/spdlog-rs/pattern.rs index 7431159..47db21f 100644 --- a/spdlog/benches/spdlog-rs/pattern.rs +++ b/spdlog/benches/spdlog-rs/pattern.rs @@ -22,13 +22,13 @@ include!(concat!( )); use test_utils::*; -struct BenchSink { +struct BenchSink<'a, F> { formatter: F, buffer: RefCell, - ctx: RefCell, + ctx: RefCell>, } -impl BenchSink { +impl BenchSink<'_, F> { fn new(formatter: F) -> Self { Self { formatter, @@ -40,9 +40,9 @@ impl BenchSink { // I think we're just testing benchmarks here, and they should not be executed // in parallel, so the data race from `buffer` shouldn't be an problem? -unsafe impl Sync for BenchSink {} +unsafe impl Sync for BenchSink<'_, F> {} -impl Sink for BenchSink { +impl Sink for BenchSink<'_, F> { fn log(&self, record: &Record) -> spdlog::Result<()> { self.formatter.format( record, diff --git a/spdlog/src/formatter/full_formatter.rs b/spdlog/src/formatter/full_formatter.rs index 17693aa..c74b9b8 100644 --- a/spdlog/src/formatter/full_formatter.rs +++ b/spdlog/src/formatter/full_formatter.rs @@ -5,7 +5,7 @@ use std::fmt::{self, Write}; use cfg_if::cfg_if; use crate::{ - formatter::{Formatter, FormatterContext, LOCAL_TIME_CACHER}, + formatter::{fmt_with_time, Formatter, FormatterContext, TimeDate}, Error, Record, StringBuf, __EOL, }; @@ -62,15 +62,14 @@ impl FullFormatter { } } - { - let mut local_time_cacher = LOCAL_TIME_CACHER.lock(); - let mut time = local_time_cacher.get(record.time()); + fmt_with_time(ctx, record, |mut time: TimeDate| { dest.write_str("[")?; dest.write_str(time.full_second_str())?; dest.write_str(".")?; write!(dest, "{:03}", time.millisecond())?; dest.write_str("] [")?; - } + Ok(()) + })?; if let Some(logger_name) = record.logger_name() { dest.write_str(logger_name)?; diff --git a/spdlog/src/formatter/local_time_cacher.rs b/spdlog/src/formatter/local_time_cacher.rs index 438e96a..6dd29a7 100644 --- a/spdlog/src/formatter/local_time_cacher.rs +++ b/spdlog/src/formatter/local_time_cacher.rs @@ -1,13 +1,24 @@ -use std::time::SystemTime; +use std::{fmt, time::SystemTime}; use chrono::prelude::*; use once_cell::sync::Lazy; -use crate::sync::*; +use crate::{formatter::FormatterContext, sync::*, Record}; -pub(crate) static LOCAL_TIME_CACHER: Lazy> = +static LOCAL_TIME_CACHER: Lazy> = Lazy::new(|| SpinMutex::new(LocalTimeCacher::new())); +pub(crate) fn fmt_with_time(ctx: &mut FormatterContext, record: &Record, mut callback: F) -> R +where + F: FnMut(TimeDate) -> R, +{ + if let Some(time_date) = ctx.locked_time_date.as_mut() { + callback(time_date.get()) + } else { + callback(LOCAL_TIME_CACHER.lock().get(record.time())) + } +} + #[derive(Clone)] pub(crate) struct LocalTimeCacher { stored_key: CacheKey, @@ -91,11 +102,11 @@ impl LocalTimeCacher { self.stored_key = cache_key; } - TimeDate::new( - self.cache_values.as_mut().unwrap(), - reduced_nanosecond, + TimeDate { + cached: self.cache_values.as_mut().unwrap(), + nanosecond: reduced_nanosecond, millisecond, - ) + } } } @@ -128,15 +139,6 @@ macro_rules! impl_cache_fields_str_getter { } impl<'a> TimeDate<'a> { - #[must_use] - fn new(cached: &'a mut CacheValues, nanosecond: u32, millisecond: u32) -> Self { - Self { - cached, - nanosecond, - millisecond, - } - } - #[must_use] pub(crate) fn full_second_str(&mut self) -> &str { if self.cached.full_second_str.is_none() { @@ -361,6 +363,41 @@ impl CacheValues { } } +pub(crate) struct TimeDateLocked<'a> { + cached: SpinMutexGuard<'a, LocalTimeCacher>, + nanosecond: u32, + millisecond: u32, +} + +impl<'a> TimeDateLocked<'a> { + #[must_use] + pub(crate) fn new(system_time: SystemTime) -> Self { + let mut cached = LOCAL_TIME_CACHER.lock(); + let time_date = cached.get(system_time); + let (nanosecond, millisecond) = (time_date.nanosecond, time_date.millisecond); + Self { + cached, + nanosecond, + millisecond, + } + } + + #[must_use] + pub(crate) fn get(&mut self) -> TimeDate<'_> { + TimeDate { + cached: self.cached.cache_values.as_mut().unwrap(), + nanosecond: self.nanosecond, + millisecond: self.millisecond, + } + } +} + +impl fmt::Debug for TimeDateLocked<'_> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("TimeDateLocked").finish() + } +} + #[cfg(test)] mod tests { use super::*; diff --git a/spdlog/src/formatter/mod.rs b/spdlog/src/formatter/mod.rs index b3c6cc3..9c7f305 100644 --- a/spdlog/src/formatter/mod.rs +++ b/spdlog/src/formatter/mod.rs @@ -95,15 +95,20 @@ clone_trait_object!(Formatter); /// Provides context for formatters. #[derive(Debug, Default)] -pub struct FormatterContext { +pub struct FormatterContext<'a> { style_range: Option>, + // Set to `Some` if the cached date time is locked in the upper caller. + locked_time_date: Option>, } -impl FormatterContext { +impl FormatterContext<'_> { /// Constructs a `FormatterContext`. #[must_use] pub fn new() -> Self { - Self { style_range: None } + Self { + style_range: None, + locked_time_date: None, + } } /// Sets style range (in bytes) of the formatted text. diff --git a/spdlog/src/formatter/pattern_formatter/mod.rs b/spdlog/src/formatter/pattern_formatter/mod.rs index 533741a..29a97df 100644 --- a/spdlog/src/formatter/pattern_formatter/mod.rs +++ b/spdlog/src/formatter/pattern_formatter/mod.rs @@ -12,7 +12,7 @@ use dyn_clone::*; pub use runtime::*; use crate::{ - formatter::{Formatter, FormatterContext}, + formatter::{Formatter, FormatterContext, TimeDate, TimeDateLocked}, Error, Record, StringBuf, }; @@ -381,8 +381,12 @@ where } }; - let mut pat_ctx = PatternContext::new(fmt_ctx); - self.pattern.format(record, dest, &mut pat_ctx)?; + fmt_ctx.locked_time_date = Some(TimeDateLocked::new(record.time())); + { + let mut pat_ctx = PatternContext { fmt_ctx }; + self.pattern.format(record, dest, &mut pat_ctx)?; + } + fmt_ctx.locked_time_date = None; Ok(()) } } @@ -391,15 +395,14 @@ where /// /// There is nothing to set up here at the moment, reserved for future use. #[derive(Debug)] -pub struct PatternContext<'a> { - fmt_ctx: &'a mut FormatterContext, +pub struct PatternContext<'a, 'b> { + fmt_ctx: &'a mut FormatterContext<'b>, } -impl<'a> PatternContext<'a> { - /// Creates a new `PatternContext` object. +impl PatternContext<'_, '_> { #[must_use] - fn new(fmt_ctx: &'a mut FormatterContext) -> Self { - Self { fmt_ctx } + fn time_date(&mut self) -> TimeDate { + self.fmt_ctx.locked_time_date.as_mut().unwrap().get() } } @@ -1221,10 +1224,12 @@ pub mod tests { let record = get_mock_record(); let mut output = StringBuf::new(); let mut fmt_ctx = FormatterContext::new(); - let mut pat_ctx = PatternContext::new(&mut fmt_ctx); - - let format_result = pattern.format(&record, &mut output, &mut pat_ctx); - assert!(format_result.is_ok()); + fmt_ctx.locked_time_date = Some(TimeDateLocked::new(record.time())); + let mut pat_ctx = PatternContext { + fmt_ctx: &mut fmt_ctx, + }; + pattern.format(&record, &mut output, &mut pat_ctx).unwrap(); + fmt_ctx.locked_time_date = None; assert_eq!(output.as_str(), formatted.as_ref()); assert_eq!(fmt_ctx.style_range(), style_range); diff --git a/spdlog/src/formatter/pattern_formatter/pattern/datetime.rs b/spdlog/src/formatter/pattern_formatter/pattern/datetime.rs index 6afd17a..383bc10 100644 --- a/spdlog/src/formatter/pattern_formatter/pattern/datetime.rs +++ b/spdlog/src/formatter/pattern_formatter/pattern/datetime.rs @@ -1,10 +1,7 @@ use std::{fmt::Write, marker::PhantomData}; use crate::{ - formatter::{ - local_time_cacher::LOCAL_TIME_CACHER, - pattern_formatter::{Pattern, PatternContext}, - }, + formatter::pattern_formatter::{Pattern, PatternContext}, Error, Record, StringBuf, }; @@ -16,17 +13,12 @@ pub struct AbbrWeekdayName; impl Pattern for AbbrWeekdayName { fn format( &self, - record: &Record, + _record: &Record, dest: &mut StringBuf, - _ctx: &mut PatternContext, + ctx: &mut PatternContext, ) -> crate::Result<()> { - let name = LOCAL_TIME_CACHER - .lock() - .get(record.time()) - .weekday_name() - .short; - - dest.write_str(name).map_err(Error::FormatRecord) + dest.write_str(ctx.time_date().weekday_name().short) + .map_err(Error::FormatRecord) } } @@ -38,17 +30,12 @@ pub struct WeekdayName; impl Pattern for WeekdayName { fn format( &self, - record: &Record, + _record: &Record, dest: &mut StringBuf, - _ctx: &mut PatternContext, + ctx: &mut PatternContext, ) -> crate::Result<()> { - let name = LOCAL_TIME_CACHER - .lock() - .get(record.time()) - .weekday_name() - .full; - - dest.write_str(name).map_err(Error::FormatRecord) + dest.write_str(ctx.time_date().weekday_name().full) + .map_err(Error::FormatRecord) } } @@ -60,17 +47,12 @@ pub struct AbbrMonthName; impl Pattern for AbbrMonthName { fn format( &self, - record: &Record, + _record: &Record, dest: &mut StringBuf, - _ctx: &mut PatternContext, + ctx: &mut PatternContext, ) -> crate::Result<()> { - let name = LOCAL_TIME_CACHER - .lock() - .get(record.time()) - .month_name() - .short; - - dest.write_str(name).map_err(Error::FormatRecord) + dest.write_str(ctx.time_date().month_name().short) + .map_err(Error::FormatRecord) } } @@ -82,17 +64,12 @@ pub struct MonthName; impl Pattern for MonthName { fn format( &self, - record: &Record, + _record: &Record, dest: &mut StringBuf, - _ctx: &mut PatternContext, + ctx: &mut PatternContext, ) -> crate::Result<()> { - let name = LOCAL_TIME_CACHER - .lock() - .get(record.time()) - .month_name() - .full; - - dest.write_str(name).map_err(Error::FormatRecord) + dest.write_str(ctx.time_date().month_name().full) + .map_err(Error::FormatRecord) } } @@ -104,27 +81,24 @@ pub struct FullDateTime; impl Pattern for FullDateTime { fn format( &self, - record: &Record, + _record: &Record, dest: &mut StringBuf, - _ctx: &mut PatternContext, + ctx: &mut PatternContext, ) -> crate::Result<()> { - let mut time_cacher_lock = LOCAL_TIME_CACHER.lock(); - let mut cached_time = time_cacher_lock.get(record.time()); - (|| { - dest.write_str(cached_time.weekday_name().short)?; + dest.write_str(ctx.time_date().weekday_name().short)?; dest.write_char(' ')?; - dest.write_str(cached_time.month_name().short)?; + dest.write_str(ctx.time_date().month_name().short)?; dest.write_char(' ')?; - dest.write_str(cached_time.day_str())?; + dest.write_str(ctx.time_date().day_str())?; dest.write_char(' ')?; - dest.write_str(cached_time.hour_str())?; + dest.write_str(ctx.time_date().hour_str())?; dest.write_char(':')?; - dest.write_str(cached_time.minute_str())?; + dest.write_str(ctx.time_date().minute_str())?; dest.write_char(':')?; - dest.write_str(cached_time.second_str())?; + dest.write_str(ctx.time_date().second_str())?; dest.write_char(' ')?; - dest.write_str(cached_time.year_str()) + dest.write_str(ctx.time_date().year_str()) })() .map_err(Error::FormatRecord) } @@ -138,11 +112,11 @@ pub struct ShortYear; impl Pattern for ShortYear { fn format( &self, - record: &Record, + _record: &Record, dest: &mut StringBuf, - _ctx: &mut PatternContext, + ctx: &mut PatternContext, ) -> crate::Result<()> { - dest.write_str(LOCAL_TIME_CACHER.lock().get(record.time()).year_short_str()) + dest.write_str(ctx.time_date().year_short_str()) .map_err(Error::FormatRecord) } } @@ -155,11 +129,11 @@ pub struct Year; impl Pattern for Year { fn format( &self, - record: &Record, + _record: &Record, dest: &mut StringBuf, - _ctx: &mut PatternContext, + ctx: &mut PatternContext, ) -> crate::Result<()> { - dest.write_str(LOCAL_TIME_CACHER.lock().get(record.time()).year_str()) + dest.write_str(ctx.time_date().year_str()) .map_err(Error::FormatRecord) } } @@ -172,19 +146,16 @@ pub struct Date; impl Pattern for Date { fn format( &self, - record: &Record, + _record: &Record, dest: &mut StringBuf, - _ctx: &mut PatternContext, + ctx: &mut PatternContext, ) -> crate::Result<()> { - let mut local_cacher_lock = LOCAL_TIME_CACHER.lock(); - let mut cached_time = local_cacher_lock.get(record.time()); - (|| { - dest.write_str(cached_time.year_str())?; + dest.write_str(ctx.time_date().year_str())?; dest.write_char('-')?; - dest.write_str(cached_time.month_str())?; + dest.write_str(ctx.time_date().month_str())?; dest.write_char('-')?; - dest.write_str(cached_time.day_str()) + dest.write_str(ctx.time_date().day_str()) })() .map_err(Error::FormatRecord) } @@ -198,19 +169,16 @@ pub struct ShortDate; impl Pattern for ShortDate { fn format( &self, - record: &Record, + _record: &Record, dest: &mut StringBuf, - _ctx: &mut PatternContext, + ctx: &mut PatternContext, ) -> crate::Result<()> { - let mut local_cacher_lock = LOCAL_TIME_CACHER.lock(); - let mut cached_time = local_cacher_lock.get(record.time()); - (|| { - dest.write_str(cached_time.month_str())?; + dest.write_str(ctx.time_date().month_str())?; dest.write_char('/')?; - dest.write_str(cached_time.day_str())?; + dest.write_str(ctx.time_date().day_str())?; dest.write_char('/')?; - dest.write_str(cached_time.year_short_str()) + dest.write_str(ctx.time_date().year_short_str()) })() .map_err(Error::FormatRecord) } @@ -224,11 +192,11 @@ pub struct Month; impl Pattern for Month { fn format( &self, - record: &Record, + _record: &Record, dest: &mut StringBuf, - _ctx: &mut PatternContext, + ctx: &mut PatternContext, ) -> crate::Result<()> { - dest.write_str(LOCAL_TIME_CACHER.lock().get(record.time()).month_str()) + dest.write_str(ctx.time_date().month_str()) .map_err(Error::FormatRecord) } } @@ -241,11 +209,11 @@ pub struct Day; impl Pattern for Day { fn format( &self, - record: &Record, + _record: &Record, dest: &mut StringBuf, - _ctx: &mut PatternContext, + ctx: &mut PatternContext, ) -> crate::Result<()> { - dest.write_str(LOCAL_TIME_CACHER.lock().get(record.time()).day_str()) + dest.write_str(ctx.time_date().day_str()) .map_err(Error::FormatRecord) } } @@ -258,11 +226,11 @@ pub struct Hour; impl Pattern for Hour { fn format( &self, - record: &Record, + _record: &Record, dest: &mut StringBuf, - _ctx: &mut PatternContext, + ctx: &mut PatternContext, ) -> crate::Result<()> { - dest.write_str(LOCAL_TIME_CACHER.lock().get(record.time()).hour_str()) + dest.write_str(ctx.time_date().hour_str()) .map_err(Error::FormatRecord) } } @@ -275,11 +243,11 @@ pub struct Hour12; impl Pattern for Hour12 { fn format( &self, - record: &Record, + _record: &Record, dest: &mut StringBuf, - _ctx: &mut PatternContext, + ctx: &mut PatternContext, ) -> crate::Result<()> { - dest.write_str(LOCAL_TIME_CACHER.lock().get(record.time()).hour12_str()) + dest.write_str(ctx.time_date().hour12_str()) .map_err(Error::FormatRecord) } } @@ -292,11 +260,11 @@ pub struct Minute; impl Pattern for Minute { fn format( &self, - record: &Record, + _record: &Record, dest: &mut StringBuf, - _ctx: &mut PatternContext, + ctx: &mut PatternContext, ) -> crate::Result<()> { - dest.write_str(LOCAL_TIME_CACHER.lock().get(record.time()).minute_str()) + dest.write_str(ctx.time_date().minute_str()) .map_err(Error::FormatRecord) } } @@ -309,11 +277,11 @@ pub struct Second; impl Pattern for Second { fn format( &self, - record: &Record, + _record: &Record, dest: &mut StringBuf, - _ctx: &mut PatternContext, + ctx: &mut PatternContext, ) -> crate::Result<()> { - dest.write_str(LOCAL_TIME_CACHER.lock().get(record.time()).second_str()) + dest.write_str(ctx.time_date().second_str()) .map_err(Error::FormatRecord) } } @@ -330,12 +298,11 @@ pub struct Millisecond { impl Pattern for Millisecond { fn format( &self, - record: &Record, + _record: &Record, dest: &mut StringBuf, - _ctx: &mut PatternContext, + ctx: &mut PatternContext, ) -> crate::Result<()> { - let millisecond = LOCAL_TIME_CACHER.lock().get(record.time()).millisecond(); - write!(dest, "{:03}", millisecond).map_err(Error::FormatRecord) + write!(dest, "{:03}", ctx.time_date().millisecond()).map_err(Error::FormatRecord) } } @@ -347,11 +314,11 @@ pub struct Microsecond; impl Pattern for Microsecond { fn format( &self, - record: &Record, + _record: &Record, dest: &mut StringBuf, - _ctx: &mut PatternContext, + ctx: &mut PatternContext, ) -> crate::Result<()> { - let nanosecond = LOCAL_TIME_CACHER.lock().get(record.time()).nanosecond(); + let nanosecond = ctx.time_date().nanosecond(); write!(dest, "{:06}", nanosecond / 1_000).map_err(Error::FormatRecord) } } @@ -364,12 +331,11 @@ pub struct Nanosecond; impl Pattern for Nanosecond { fn format( &self, - record: &Record, + _record: &Record, dest: &mut StringBuf, - _ctx: &mut PatternContext, + ctx: &mut PatternContext, ) -> crate::Result<()> { - let nanosecond = LOCAL_TIME_CACHER.lock().get(record.time()).nanosecond(); - write!(dest, "{:09}", nanosecond).map_err(Error::FormatRecord) + write!(dest, "{:09}", ctx.time_date().nanosecond()).map_err(Error::FormatRecord) } } @@ -381,12 +347,12 @@ pub struct AmPm; impl Pattern for AmPm { fn format( &self, - record: &Record, + _record: &Record, dest: &mut StringBuf, - _ctx: &mut PatternContext, + ctx: &mut PatternContext, ) -> crate::Result<()> { - let am_pm_str = LOCAL_TIME_CACHER.lock().get(record.time()).am_pm_str(); - dest.write_str(am_pm_str).map_err(Error::FormatRecord) + dest.write_str(ctx.time_date().am_pm_str()) + .map_err(Error::FormatRecord) } } @@ -398,21 +364,18 @@ pub struct Time12; impl Pattern for Time12 { fn format( &self, - record: &Record, + _record: &Record, dest: &mut StringBuf, - _ctx: &mut PatternContext, + ctx: &mut PatternContext, ) -> crate::Result<()> { - let mut time_cacher_lock = LOCAL_TIME_CACHER.lock(); - let mut cached_time = time_cacher_lock.get(record.time()); - (|| { - dest.write_str(cached_time.hour12_str())?; + dest.write_str(ctx.time_date().hour12_str())?; dest.write_char(':')?; - dest.write_str(cached_time.minute_str())?; + dest.write_str(ctx.time_date().minute_str())?; dest.write_char(':')?; - dest.write_str(cached_time.second_str())?; + dest.write_str(ctx.time_date().second_str())?; dest.write_str(" ")?; - dest.write_str(cached_time.am_pm_str()) + dest.write_str(ctx.time_date().am_pm_str()) })() .map_err(Error::FormatRecord) } @@ -426,17 +389,14 @@ pub struct ShortTime; impl Pattern for ShortTime { fn format( &self, - record: &Record, + _record: &Record, dest: &mut StringBuf, - _ctx: &mut PatternContext, + ctx: &mut PatternContext, ) -> crate::Result<()> { - let mut time_cacher_lock = LOCAL_TIME_CACHER.lock(); - let mut cached_time = time_cacher_lock.get(record.time()); - (|| { - dest.write_str(cached_time.hour_str())?; + dest.write_str(ctx.time_date().hour_str())?; dest.write_char(':')?; - dest.write_str(cached_time.minute_str()) + dest.write_str(ctx.time_date().minute_str()) })() .map_err(Error::FormatRecord) } @@ -450,19 +410,16 @@ pub struct Time; impl Pattern for Time { fn format( &self, - record: &Record, + _record: &Record, dest: &mut StringBuf, - _ctx: &mut PatternContext, + ctx: &mut PatternContext, ) -> crate::Result<()> { - let mut time_cacher_lock = LOCAL_TIME_CACHER.lock(); - let mut cached_time = time_cacher_lock.get(record.time()); - (|| { - dest.write_str(cached_time.hour_str())?; + dest.write_str(ctx.time_date().hour_str())?; dest.write_char(':')?; - dest.write_str(cached_time.minute_str())?; + dest.write_str(ctx.time_date().minute_str())?; dest.write_char(':')?; - dest.write_str(cached_time.second_str()) + dest.write_str(ctx.time_date().second_str()) })() .map_err(Error::FormatRecord) } @@ -476,11 +433,11 @@ pub struct TzOffset; impl Pattern for TzOffset { fn format( &self, - record: &Record, + _record: &Record, dest: &mut StringBuf, - _ctx: &mut PatternContext, + ctx: &mut PatternContext, ) -> crate::Result<()> { - dest.write_str(LOCAL_TIME_CACHER.lock().get(record.time()).tz_offset_str()) + dest.write_str(ctx.time_date().tz_offset_str()) .map_err(Error::FormatRecord) } } @@ -493,16 +450,11 @@ pub struct UnixTimestamp; impl Pattern for UnixTimestamp { fn format( &self, - record: &Record, + _record: &Record, dest: &mut StringBuf, - _ctx: &mut PatternContext, + ctx: &mut PatternContext, ) -> crate::Result<()> { - dest.write_str( - LOCAL_TIME_CACHER - .lock() - .get(record.time()) - .unix_timestamp_str(), - ) - .map_err(Error::FormatRecord) + dest.write_str(ctx.time_date().unix_timestamp_str()) + .map_err(Error::FormatRecord) } }