From c49562c5edb176e78ee4c1185929fe016ba10fc2 Mon Sep 17 00:00:00 2001 From: Kybxd <627940450@qq.com> Date: Sat, 23 Aug 2025 14:39:21 +0800 Subject: [PATCH 1/7] feat: thread safe localtime --- .../embed/logger.pc.cc | 23 ++++++++++++++----- .../embed/logger.pc.h | 5 +++- .../src/protoconf/logger.pc.cc | 23 ++++++++++++++----- .../src/protoconf/logger.pc.h | 5 +++- 4 files changed, 42 insertions(+), 14 deletions(-) diff --git a/cmd/protoc-gen-cpp-tableau-loader/embed/logger.pc.cc b/cmd/protoc-gen-cpp-tableau-loader/embed/logger.pc.cc index 4ecc2908..d0ece8c4 100644 --- a/cmd/protoc-gen-cpp-tableau-loader/embed/logger.pc.cc +++ b/cmd/protoc-gen-cpp-tableau-loader/embed/logger.pc.cc @@ -94,12 +94,23 @@ void DefaultWrite(std::ostream* os, const SourceLocation& loc, const LevelInfo& // clang-format on } -std::ostream& operator<<(std::ostream& os, const Now&) { - auto now = std::chrono::system_clock::now(); - auto now_time_t = std::chrono::system_clock::to_time_t(now); - auto now_us = std::chrono::duration_cast(now.time_since_epoch()) % 1000000; - return os << std::put_time(std::localtime(&now_time_t), "%F %T") << "." << std::setw(6) << std::setfill('0') - << now_us.count(); +std::tm* Now::LocalTime(std::time_t time, std::tm* tm) const { +#ifdef _WIN32 + localtime_s(tm, &time); +#else + localtime_r(&time, tm); +#endif + return tm; +} + +std::ostream& operator<<(std::ostream& os, const Now& n) { + using namespace std::chrono; + static thread_local std::tm tm; + auto duration = system_clock::now().time_since_epoch(); + auto secs = duration_cast(duration); + auto micros = duration_cast(duration - secs); + return os << std::put_time(n.LocalTime(static_cast(secs.count()), &tm), "%F %T") << "." << std::setw(6) + << std::setfill('0') << micros.count(); } } // namespace log diff --git a/cmd/protoc-gen-cpp-tableau-loader/embed/logger.pc.h b/cmd/protoc-gen-cpp-tableau-loader/embed/logger.pc.h index 33a161b8..dc1e4b99 100644 --- a/cmd/protoc-gen-cpp-tableau-loader/embed/logger.pc.h +++ b/cmd/protoc-gen-cpp-tableau-loader/embed/logger.pc.h @@ -64,7 +64,10 @@ class Logger { Writer writer_; }; -class Now {}; +class Now { + public: + std::tm* LocalTime(std::time_t time, std::tm* tm) const; +}; std::ostream& operator<<(std::ostream&, const Now&); Logger* DefaultLogger(); diff --git a/test/cpp-tableau-loader/src/protoconf/logger.pc.cc b/test/cpp-tableau-loader/src/protoconf/logger.pc.cc index 747ce28d..e6f1dba6 100644 --- a/test/cpp-tableau-loader/src/protoconf/logger.pc.cc +++ b/test/cpp-tableau-loader/src/protoconf/logger.pc.cc @@ -99,12 +99,23 @@ void DefaultWrite(std::ostream* os, const SourceLocation& loc, const LevelInfo& // clang-format on } -std::ostream& operator<<(std::ostream& os, const Now&) { - auto now = std::chrono::system_clock::now(); - auto now_time_t = std::chrono::system_clock::to_time_t(now); - auto now_us = std::chrono::duration_cast(now.time_since_epoch()) % 1000000; - return os << std::put_time(std::localtime(&now_time_t), "%F %T") << "." << std::setw(6) << std::setfill('0') - << now_us.count(); +std::tm* Now::LocalTime(std::time_t time, std::tm* tm) const { +#ifdef _WIN32 + localtime_s(tm, &time); +#else + localtime_r(&time, tm); +#endif + return tm; +} + +std::ostream& operator<<(std::ostream& os, const Now& n) { + using namespace std::chrono; + static thread_local std::tm tm; + auto duration = system_clock::now().time_since_epoch(); + auto secs = duration_cast(duration); + auto micros = duration_cast(duration - secs); + return os << std::put_time(n.LocalTime(static_cast(secs.count()), &tm), "%F %T") << "." << std::setw(6) + << std::setfill('0') << micros.count(); } } // namespace log diff --git a/test/cpp-tableau-loader/src/protoconf/logger.pc.h b/test/cpp-tableau-loader/src/protoconf/logger.pc.h index 592c82b7..a6e21848 100644 --- a/test/cpp-tableau-loader/src/protoconf/logger.pc.h +++ b/test/cpp-tableau-loader/src/protoconf/logger.pc.h @@ -69,7 +69,10 @@ class Logger { Writer writer_; }; -class Now {}; +class Now { + public: + std::tm* LocalTime(std::time_t time, std::tm* tm) const; +}; std::ostream& operator<<(std::ostream&, const Now&); Logger* DefaultLogger(); From 62b3d4f2afd042dfaf1973d7dd10298dbee17e2e Mon Sep 17 00:00:00 2001 From: Kybxd <627940450@qq.com> Date: Sat, 23 Aug 2025 15:17:56 +0800 Subject: [PATCH 2/7] feat: better support for c++20 --- cmd/protoc-gen-cpp-tableau-loader/embed/logger.pc.cc | 8 +++++++- test/cpp-tableau-loader/src/protoconf/logger.pc.cc | 8 +++++++- 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/cmd/protoc-gen-cpp-tableau-loader/embed/logger.pc.cc b/cmd/protoc-gen-cpp-tableau-loader/embed/logger.pc.cc index d0ece8c4..09a5928a 100644 --- a/cmd/protoc-gen-cpp-tableau-loader/embed/logger.pc.cc +++ b/cmd/protoc-gen-cpp-tableau-loader/embed/logger.pc.cc @@ -105,12 +105,18 @@ std::tm* Now::LocalTime(std::time_t time, std::tm* tm) const { std::ostream& operator<<(std::ostream& os, const Now& n) { using namespace std::chrono; + auto now = system_clock::now(); +#if __cplusplus >= 202002L + auto zt = zoned_time(std::chrono::current_zone(), floor(now)); + return os << std::format("{:%F %T}", zt); +#else static thread_local std::tm tm; - auto duration = system_clock::now().time_since_epoch(); + auto duration = now.time_since_epoch(); auto secs = duration_cast(duration); auto micros = duration_cast(duration - secs); return os << std::put_time(n.LocalTime(static_cast(secs.count()), &tm), "%F %T") << "." << std::setw(6) << std::setfill('0') << micros.count(); +#endif } } // namespace log diff --git a/test/cpp-tableau-loader/src/protoconf/logger.pc.cc b/test/cpp-tableau-loader/src/protoconf/logger.pc.cc index e6f1dba6..b30f091e 100644 --- a/test/cpp-tableau-loader/src/protoconf/logger.pc.cc +++ b/test/cpp-tableau-loader/src/protoconf/logger.pc.cc @@ -110,12 +110,18 @@ std::tm* Now::LocalTime(std::time_t time, std::tm* tm) const { std::ostream& operator<<(std::ostream& os, const Now& n) { using namespace std::chrono; + auto now = system_clock::now(); +#if __cplusplus >= 202002L + auto zt = zoned_time(std::chrono::current_zone(), floor(now)); + return os << std::format("{:%F %T}", zt); +#else static thread_local std::tm tm; - auto duration = system_clock::now().time_since_epoch(); + auto duration = now.time_since_epoch(); auto secs = duration_cast(duration); auto micros = duration_cast(duration - secs); return os << std::put_time(n.LocalTime(static_cast(secs.count()), &tm), "%F %T") << "." << std::setw(6) << std::setfill('0') << micros.count(); +#endif } } // namespace log From 73b3677cc6ac4cecb817a05ef898ab9d6b7fa682 Mon Sep 17 00:00:00 2001 From: Kybxd <627940450@qq.com> Date: Sat, 23 Aug 2025 15:26:22 +0800 Subject: [PATCH 3/7] feat: ignore std::chrono:: --- cmd/protoc-gen-cpp-tableau-loader/embed/logger.pc.cc | 2 +- test/cpp-tableau-loader/src/protoconf/logger.pc.cc | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/cmd/protoc-gen-cpp-tableau-loader/embed/logger.pc.cc b/cmd/protoc-gen-cpp-tableau-loader/embed/logger.pc.cc index 09a5928a..d195cc02 100644 --- a/cmd/protoc-gen-cpp-tableau-loader/embed/logger.pc.cc +++ b/cmd/protoc-gen-cpp-tableau-loader/embed/logger.pc.cc @@ -107,7 +107,7 @@ std::ostream& operator<<(std::ostream& os, const Now& n) { using namespace std::chrono; auto now = system_clock::now(); #if __cplusplus >= 202002L - auto zt = zoned_time(std::chrono::current_zone(), floor(now)); + auto zt = zoned_time(current_zone(), floor(now)); return os << std::format("{:%F %T}", zt); #else static thread_local std::tm tm; diff --git a/test/cpp-tableau-loader/src/protoconf/logger.pc.cc b/test/cpp-tableau-loader/src/protoconf/logger.pc.cc index b30f091e..a243a6ff 100644 --- a/test/cpp-tableau-loader/src/protoconf/logger.pc.cc +++ b/test/cpp-tableau-loader/src/protoconf/logger.pc.cc @@ -112,7 +112,7 @@ std::ostream& operator<<(std::ostream& os, const Now& n) { using namespace std::chrono; auto now = system_clock::now(); #if __cplusplus >= 202002L - auto zt = zoned_time(std::chrono::current_zone(), floor(now)); + auto zt = zoned_time(current_zone(), floor(now)); return os << std::format("{:%F %T}", zt); #else static thread_local std::tm tm; From 537a97034879234d6fa6591fef4838094d13163b Mon Sep 17 00:00:00 2001 From: Kybxd <627940450@qq.com> Date: Sat, 23 Aug 2025 15:39:36 +0800 Subject: [PATCH 4/7] feat: remove func LocalTime --- .../embed/logger.pc.cc | 20 ++++++++----------- .../embed/logger.pc.h | 5 +---- .../src/protoconf/logger.pc.cc | 20 ++++++++----------- .../src/protoconf/logger.pc.h | 5 +---- 4 files changed, 18 insertions(+), 32 deletions(-) diff --git a/cmd/protoc-gen-cpp-tableau-loader/embed/logger.pc.cc b/cmd/protoc-gen-cpp-tableau-loader/embed/logger.pc.cc index d195cc02..fe96530a 100644 --- a/cmd/protoc-gen-cpp-tableau-loader/embed/logger.pc.cc +++ b/cmd/protoc-gen-cpp-tableau-loader/embed/logger.pc.cc @@ -94,16 +94,7 @@ void DefaultWrite(std::ostream* os, const SourceLocation& loc, const LevelInfo& // clang-format on } -std::tm* Now::LocalTime(std::time_t time, std::tm* tm) const { -#ifdef _WIN32 - localtime_s(tm, &time); -#else - localtime_r(&time, tm); -#endif - return tm; -} - -std::ostream& operator<<(std::ostream& os, const Now& n) { +std::ostream& operator<<(std::ostream& os, const Now&) { using namespace std::chrono; auto now = system_clock::now(); #if __cplusplus >= 202002L @@ -111,11 +102,16 @@ std::ostream& operator<<(std::ostream& os, const Now& n) { return os << std::format("{:%F %T}", zt); #else static thread_local std::tm tm; + auto now_t = system_clock::to_time_t(now); +#ifdef _WIN32 + localtime_s(&tm, &now_t); +#else + localtime_r(&now_t, &tm); +#endif auto duration = now.time_since_epoch(); auto secs = duration_cast(duration); auto micros = duration_cast(duration - secs); - return os << std::put_time(n.LocalTime(static_cast(secs.count()), &tm), "%F %T") << "." << std::setw(6) - << std::setfill('0') << micros.count(); + return os << std::put_time(&tm, "%F %T") << "." << std::setw(6) << std::setfill('0') << micros.count(); #endif } diff --git a/cmd/protoc-gen-cpp-tableau-loader/embed/logger.pc.h b/cmd/protoc-gen-cpp-tableau-loader/embed/logger.pc.h index dc1e4b99..33a161b8 100644 --- a/cmd/protoc-gen-cpp-tableau-loader/embed/logger.pc.h +++ b/cmd/protoc-gen-cpp-tableau-loader/embed/logger.pc.h @@ -64,10 +64,7 @@ class Logger { Writer writer_; }; -class Now { - public: - std::tm* LocalTime(std::time_t time, std::tm* tm) const; -}; +class Now {}; std::ostream& operator<<(std::ostream&, const Now&); Logger* DefaultLogger(); diff --git a/test/cpp-tableau-loader/src/protoconf/logger.pc.cc b/test/cpp-tableau-loader/src/protoconf/logger.pc.cc index a243a6ff..2e173ed7 100644 --- a/test/cpp-tableau-loader/src/protoconf/logger.pc.cc +++ b/test/cpp-tableau-loader/src/protoconf/logger.pc.cc @@ -99,16 +99,7 @@ void DefaultWrite(std::ostream* os, const SourceLocation& loc, const LevelInfo& // clang-format on } -std::tm* Now::LocalTime(std::time_t time, std::tm* tm) const { -#ifdef _WIN32 - localtime_s(tm, &time); -#else - localtime_r(&time, tm); -#endif - return tm; -} - -std::ostream& operator<<(std::ostream& os, const Now& n) { +std::ostream& operator<<(std::ostream& os, const Now&) { using namespace std::chrono; auto now = system_clock::now(); #if __cplusplus >= 202002L @@ -116,11 +107,16 @@ std::ostream& operator<<(std::ostream& os, const Now& n) { return os << std::format("{:%F %T}", zt); #else static thread_local std::tm tm; + auto now_t = system_clock::to_time_t(now); +#ifdef _WIN32 + localtime_s(&tm, &now_t); +#else + localtime_r(&now_t, &tm); +#endif auto duration = now.time_since_epoch(); auto secs = duration_cast(duration); auto micros = duration_cast(duration - secs); - return os << std::put_time(n.LocalTime(static_cast(secs.count()), &tm), "%F %T") << "." << std::setw(6) - << std::setfill('0') << micros.count(); + return os << std::put_time(&tm, "%F %T") << "." << std::setw(6) << std::setfill('0') << micros.count(); #endif } diff --git a/test/cpp-tableau-loader/src/protoconf/logger.pc.h b/test/cpp-tableau-loader/src/protoconf/logger.pc.h index a6e21848..592c82b7 100644 --- a/test/cpp-tableau-loader/src/protoconf/logger.pc.h +++ b/test/cpp-tableau-loader/src/protoconf/logger.pc.h @@ -69,10 +69,7 @@ class Logger { Writer writer_; }; -class Now { - public: - std::tm* LocalTime(std::time_t time, std::tm* tm) const; -}; +class Now {}; std::ostream& operator<<(std::ostream&, const Now&); Logger* DefaultLogger(); From 310f500fb4ba2d0717e6aa54cfc35fc52f461ab1 Mon Sep 17 00:00:00 2001 From: Kybxd <627940450@qq.com> Date: Sat, 23 Aug 2025 16:17:05 +0800 Subject: [PATCH 5/7] feat: use namespace sc --- cmd/protoc-gen-cpp-tableau-loader/embed/logger.pc.cc | 12 ++++++------ test/cpp-tableau-loader/src/protoconf/logger.pc.cc | 12 ++++++------ 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/cmd/protoc-gen-cpp-tableau-loader/embed/logger.pc.cc b/cmd/protoc-gen-cpp-tableau-loader/embed/logger.pc.cc index fe96530a..57812dda 100644 --- a/cmd/protoc-gen-cpp-tableau-loader/embed/logger.pc.cc +++ b/cmd/protoc-gen-cpp-tableau-loader/embed/logger.pc.cc @@ -95,22 +95,22 @@ void DefaultWrite(std::ostream* os, const SourceLocation& loc, const LevelInfo& } std::ostream& operator<<(std::ostream& os, const Now&) { - using namespace std::chrono; - auto now = system_clock::now(); + namespace sc = std::chrono; + auto now = sc::system_clock::now(); #if __cplusplus >= 202002L - auto zt = zoned_time(current_zone(), floor(now)); + auto zt = sc::zoned_time(sc::current_zone(), sc::floor(now)); return os << std::format("{:%F %T}", zt); #else static thread_local std::tm tm; - auto now_t = system_clock::to_time_t(now); + auto now_t = sc::system_clock::to_time_t(now); #ifdef _WIN32 localtime_s(&tm, &now_t); #else localtime_r(&now_t, &tm); #endif auto duration = now.time_since_epoch(); - auto secs = duration_cast(duration); - auto micros = duration_cast(duration - secs); + auto secs = sc::duration_cast(duration); + auto micros = sc::duration_cast(duration - secs); return os << std::put_time(&tm, "%F %T") << "." << std::setw(6) << std::setfill('0') << micros.count(); #endif } diff --git a/test/cpp-tableau-loader/src/protoconf/logger.pc.cc b/test/cpp-tableau-loader/src/protoconf/logger.pc.cc index 2e173ed7..d53016c8 100644 --- a/test/cpp-tableau-loader/src/protoconf/logger.pc.cc +++ b/test/cpp-tableau-loader/src/protoconf/logger.pc.cc @@ -100,22 +100,22 @@ void DefaultWrite(std::ostream* os, const SourceLocation& loc, const LevelInfo& } std::ostream& operator<<(std::ostream& os, const Now&) { - using namespace std::chrono; - auto now = system_clock::now(); + namespace sc = std::chrono; + auto now = sc::system_clock::now(); #if __cplusplus >= 202002L - auto zt = zoned_time(current_zone(), floor(now)); + auto zt = sc::zoned_time(sc::current_zone(), sc::floor(now)); return os << std::format("{:%F %T}", zt); #else static thread_local std::tm tm; - auto now_t = system_clock::to_time_t(now); + auto now_t = sc::system_clock::to_time_t(now); #ifdef _WIN32 localtime_s(&tm, &now_t); #else localtime_r(&now_t, &tm); #endif auto duration = now.time_since_epoch(); - auto secs = duration_cast(duration); - auto micros = duration_cast(duration - secs); + auto secs = sc::duration_cast(duration); + auto micros = sc::duration_cast(duration - secs); return os << std::put_time(&tm, "%F %T") << "." << std::setw(6) << std::setfill('0') << micros.count(); #endif } From 637531ad6791fbb21863ffca4d2f861057c85fc4 Mon Sep 17 00:00:00 2001 From: Kybxd <627940450@qq.com> Date: Mon, 25 Aug 2025 10:29:27 +0800 Subject: [PATCH 6/7] feat: revert changes --- cmd/protoc-gen-cpp-tableau-loader/embed/logger.pc.cc | 11 +++++------ test/cpp-tableau-loader/src/protoconf/logger.pc.cc | 11 +++++------ 2 files changed, 10 insertions(+), 12 deletions(-) diff --git a/cmd/protoc-gen-cpp-tableau-loader/embed/logger.pc.cc b/cmd/protoc-gen-cpp-tableau-loader/embed/logger.pc.cc index 57812dda..735ebb92 100644 --- a/cmd/protoc-gen-cpp-tableau-loader/embed/logger.pc.cc +++ b/cmd/protoc-gen-cpp-tableau-loader/embed/logger.pc.cc @@ -95,22 +95,21 @@ void DefaultWrite(std::ostream* os, const SourceLocation& loc, const LevelInfo& } std::ostream& operator<<(std::ostream& os, const Now&) { - namespace sc = std::chrono; - auto now = sc::system_clock::now(); + auto now = std::chrono::system_clock::now(); #if __cplusplus >= 202002L - auto zt = sc::zoned_time(sc::current_zone(), sc::floor(now)); + auto zt = std::chrono::zoned_time(std::chrono::current_zone(), std::chrono::floor(now)); return os << std::format("{:%F %T}", zt); #else static thread_local std::tm tm; - auto now_t = sc::system_clock::to_time_t(now); + auto now_t = std::chrono::system_clock::to_time_t(now); #ifdef _WIN32 localtime_s(&tm, &now_t); #else localtime_r(&now_t, &tm); #endif auto duration = now.time_since_epoch(); - auto secs = sc::duration_cast(duration); - auto micros = sc::duration_cast(duration - secs); + auto secs = std::chrono::duration_cast(duration); + auto micros = std::chrono::duration_cast(duration - secs); return os << std::put_time(&tm, "%F %T") << "." << std::setw(6) << std::setfill('0') << micros.count(); #endif } diff --git a/test/cpp-tableau-loader/src/protoconf/logger.pc.cc b/test/cpp-tableau-loader/src/protoconf/logger.pc.cc index d53016c8..ec80696f 100644 --- a/test/cpp-tableau-loader/src/protoconf/logger.pc.cc +++ b/test/cpp-tableau-loader/src/protoconf/logger.pc.cc @@ -100,22 +100,21 @@ void DefaultWrite(std::ostream* os, const SourceLocation& loc, const LevelInfo& } std::ostream& operator<<(std::ostream& os, const Now&) { - namespace sc = std::chrono; - auto now = sc::system_clock::now(); + auto now = std::chrono::system_clock::now(); #if __cplusplus >= 202002L - auto zt = sc::zoned_time(sc::current_zone(), sc::floor(now)); + auto zt = std::chrono::zoned_time(std::chrono::current_zone(), std::chrono::floor(now)); return os << std::format("{:%F %T}", zt); #else static thread_local std::tm tm; - auto now_t = sc::system_clock::to_time_t(now); + auto now_t = std::chrono::system_clock::to_time_t(now); #ifdef _WIN32 localtime_s(&tm, &now_t); #else localtime_r(&now_t, &tm); #endif auto duration = now.time_since_epoch(); - auto secs = sc::duration_cast(duration); - auto micros = sc::duration_cast(duration - secs); + auto secs = std::chrono::duration_cast(duration); + auto micros = std::chrono::duration_cast(duration - secs); return os << std::put_time(&tm, "%F %T") << "." << std::setw(6) << std::setfill('0') << micros.count(); #endif } From 5ef6ad7121a72573e979279665fdc5887df21cc2 Mon Sep 17 00:00:00 2001 From: Kybxd <627940450@qq.com> Date: Mon, 25 Aug 2025 15:24:35 +0800 Subject: [PATCH 7/7] feat: use -j instead of --parallel for cmake --- README.md | 4 ++-- init.bat | 2 +- init.sh | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index f6d472e9..44cde351 100644 --- a/README.md +++ b/README.md @@ -26,7 +26,7 @@ The official config loader for [Tableau](https://github.com/tableauio/tableau). - C++17: `cmake -S . -B build` - C++20: `cmake -S . -B build -DCMAKE_CXX_STANDARD=20` - clang: `cmake -S . -B build -DCMAKE_CXX_COMPILER=clang++` -- Build: `cmake --build build --parallel 10` +- Build: `cmake --build build -j16` - Run: `./bin/loader` ### Dev at Windows @@ -36,7 +36,7 @@ The official config loader for [Tableau](https://github.com/tableauio/tableau). - CMake: - C++17: `cmake -S . -B build -G "NMake Makefiles"` - C++20: `cmake -S . -B build -G "NMake Makefiles" -DCMAKE_CXX_STANDARD=20` -- Build: `cmake --build build --parallel 10` +- Build: `cmake --build build` - Run: `.\bin\loader.exe` ### References diff --git a/init.bat b/init.bat index 6103990c..d97e1ab8 100644 --- a/init.bat +++ b/init.bat @@ -21,6 +21,6 @@ cmake -S . -B build ^ -DCMAKE_POLICY_VERSION_MINIMUM="3.5" REM Compile the code -cmake --build build --parallel 10 +cmake --build build endlocal diff --git a/init.sh b/init.sh index 092096f3..5e78d447 100755 --- a/init.sh +++ b/init.sh @@ -26,4 +26,4 @@ cmake -S . -B build \ -DCMAKE_BUILD_TYPE=Debug # Compile the code -cmake --build build --parallel 10 +cmake --build build -j16