2121#include < utility>
2222#include < vector>
2323#include < format>
24+ #include < syncstream>
2425#include " macros.h"
2526#include " stringutils.h"
2627
@@ -33,9 +34,14 @@ FCITX_DEFINE_LOG_CATEGORY(defaultCategory, "default");
3334using LogRule = std::pair<std::string, LogLevel>;
3435
3536struct LogConfig {
36- std::ostream *defaultLogStream = &std::cerr;
37- bool showTimeDate = true ;
38- } globalLogConfig;
37+ static std::ostream *defaultLogStream;
38+ static thread_local std::osyncstream localLogStream;
39+ static bool showTimeDate;
40+ };
41+
42+ std::ostream *LogConfig::defaultLogStream = &std::cerr;
43+ thread_local std::osyncstream LogConfig::localLogStream{*defaultLogStream};
44+ bool LogConfig::showTimeDate = true ;
3945
4046bool validateLogLevel (std::underlying_type_t <LogLevel> l) {
4147 return (l >= 0 &&
@@ -163,7 +169,7 @@ void Log::setLogRule(const std::string &ruleString) {
163169 auto rules = stringutils::split (ruleString, " ," );
164170 for (const auto &rule : rules) {
165171 if (rule == " notimedate" ) {
166- globalLogConfig. showTimeDate = false ;
172+ LogConfig:: showTimeDate = false ;
167173 continue ;
168174 }
169175
@@ -185,14 +191,21 @@ void Log::setLogRule(const std::string &ruleString) {
185191}
186192
187193void Log::setLogStream (std::ostream &stream) {
188- globalLogConfig. defaultLogStream = &stream;
194+ LogConfig:: defaultLogStream = &stream;
189195}
190196
191- std::ostream &Log::logStream () { return *globalLogConfig.defaultLogStream ; }
197+ std::ostream &Log::logStream () {
198+ auto *buf = LogConfig::defaultLogStream->rdbuf ();
199+ if (LogConfig::localLogStream.get_wrapped () != buf) {
200+ LogConfig::localLogStream = std::osyncstream (buf);
201+ }
202+ return LogConfig::localLogStream;
203+ }
192204
193205LogMessageBuilder::LogMessageBuilder (std::ostream &out, LogLevel l,
194206 const char *filename, int lineNumber)
195207 : out_(out) {
208+ out << std::noemit_on_flush;
196209 switch (l) {
197210 case LogLevel::Fatal:
198211 out_ << " F" ;
@@ -213,7 +226,7 @@ LogMessageBuilder::LogMessageBuilder(std::ostream &out, LogLevel l,
213226 break ;
214227 }
215228
216- if (globalLogConfig. showTimeDate ) {
229+ if (LogConfig:: showTimeDate) {
217230 try {
218231 auto now = std::chrono::time_point_cast<std::chrono::microseconds>(
219232 std::chrono::system_clock::now ());
@@ -233,6 +246,9 @@ LogMessageBuilder::LogMessageBuilder(std::ostream &out, LogLevel l,
233246 out_ << filename << " :" << lineNumber << " ] " ;
234247}
235248
236- LogMessageBuilder::~LogMessageBuilder () { out_ << ' \n ' ; }
249+ LogMessageBuilder::~LogMessageBuilder () {
250+ out_ << ' \n ' << std::emit_on_flush;
251+ out_.flush ();
252+ }
237253
238254} // namespace fcitx
0 commit comments