21
21
#include < utility>
22
22
#include < vector>
23
23
#include < format>
24
+ #include < syncstream>
24
25
#include " macros.h"
25
26
#include " stringutils.h"
26
27
@@ -33,9 +34,14 @@ FCITX_DEFINE_LOG_CATEGORY(defaultCategory, "default");
33
34
using LogRule = std::pair<std::string, LogLevel>;
34
35
35
36
struct 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 ;
39
45
40
46
bool validateLogLevel (std::underlying_type_t <LogLevel> l) {
41
47
return (l >= 0 &&
@@ -163,7 +169,7 @@ void Log::setLogRule(const std::string &ruleString) {
163
169
auto rules = stringutils::split (ruleString, " ," );
164
170
for (const auto &rule : rules) {
165
171
if (rule == " notimedate" ) {
166
- globalLogConfig. showTimeDate = false ;
172
+ LogConfig:: showTimeDate = false ;
167
173
continue ;
168
174
}
169
175
@@ -185,14 +191,21 @@ void Log::setLogRule(const std::string &ruleString) {
185
191
}
186
192
187
193
void Log::setLogStream (std::ostream &stream) {
188
- globalLogConfig. defaultLogStream = &stream;
194
+ LogConfig:: defaultLogStream = &stream;
189
195
}
190
196
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
+ }
192
204
193
205
LogMessageBuilder::LogMessageBuilder (std::ostream &out, LogLevel l,
194
206
const char *filename, int lineNumber)
195
207
: out_(out) {
208
+ out << std::noemit_on_flush;
196
209
switch (l) {
197
210
case LogLevel::Fatal:
198
211
out_ << " F" ;
@@ -213,7 +226,7 @@ LogMessageBuilder::LogMessageBuilder(std::ostream &out, LogLevel l,
213
226
break ;
214
227
}
215
228
216
- if (globalLogConfig. showTimeDate ) {
229
+ if (LogConfig:: showTimeDate) {
217
230
try {
218
231
auto now = std::chrono::time_point_cast<std::chrono::microseconds>(
219
232
std::chrono::system_clock::now ());
@@ -233,6 +246,9 @@ LogMessageBuilder::LogMessageBuilder(std::ostream &out, LogLevel l,
233
246
out_ << filename << " :" << lineNumber << " ] " ;
234
247
}
235
248
236
- LogMessageBuilder::~LogMessageBuilder () { out_ << ' \n ' ; }
249
+ LogMessageBuilder::~LogMessageBuilder () {
250
+ out_ << ' \n ' << std::emit_on_flush;
251
+ out_.flush ();
252
+ }
237
253
238
254
} // namespace fcitx
0 commit comments