--- nono/host/logger.cpp 2026/04/29 17:05:56 1.1.1.2 +++ nono/host/logger.cpp 2026/04/29 17:06:02 1.1.1.3 @@ -11,6 +11,37 @@ // Logger はモニタを持つため Object から派生しているが、(Object のもう一つの // 機能である) ログ出力は出来ない。これは自明。 +// また、ログと comdriver_stdio (特にデバッガの出力) が標準出力への出力を +// 共有するため標準出力側のみここで担当している。 +// 概念としての動作はこんな感じ。 +// +// 送信側スレッド : ログスレッド +// +// ログ/標準出力 : +// | +// +------->| queue |------+ +// | Yes +// : (ログ?)-------------+ +// | | +// : | No +------------------+ +// | | ログモニタに格納 | +// : | +------------------+ +// | | +// : | v +// | (ログを標準出力に出力?) +// : | | | +// | | Yes No | +// : +<---------+ | +// | | +// : v | +// +----------------+ | +// : | 標準出力に出力 | | +// +----------------+ | +// : | | +// +-----------+----------+ +// : | +// END + #include "logger.h" #include "monitor.h" #include "mythread.h" @@ -24,7 +55,7 @@ Logger::Logger() ClearAlias(); monitor = gMonitorManager->Regist(ID_MONITOR_LOG, this); - monitor->func = ToMonitorCallback(&Logger::MonitorUpdate); + monitor->SetCallback(&Logger::MonitorScreen); monitor->SetSize(80, 40); // 初期サイズは適当 } @@ -104,13 +135,31 @@ Logger::Terminate() cv.notify_one(); } +// 標準出力にも出力するかを設定。 +void +Logger::UseStdout(bool val) +{ + use_stdout = val; +} + // ログ書き込み。 // 他スレッドから呼ばれる。 void -Logger::Write(const char *str) +Logger::WriteLog(const char *str) { std::lock_guard lock(queue_mtx); - queue.emplace_back(str); + queue.emplace_back(LogMsg::Type::Log, str); + request |= REQ_QUEUE; + cv.notify_one(); +} + +// 標準出力への出力。 +// COMDriverStdio から呼ばれる。 +void +Logger::WriteStdout(const char *str) +{ + std::lock_guard lock(queue_mtx); + queue.emplace_back(LogMsg::Type::Stdout, str); request |= REQ_QUEUE; cv.notify_one(); } @@ -121,7 +170,7 @@ Logger::ThreadRun() SetThreadAffinityHint(AffinityClass::Light); for (;;) { - std::string utf8str; + LogMsg msg; // 何か起きるまで待つ。 { @@ -137,7 +186,7 @@ Logger::ThreadRun() request = 0; continue; } else { - utf8str = queue.front(); + msg = queue.front(); queue.pop_front(); if (queue.empty()) { request = 0; @@ -145,19 +194,32 @@ Logger::ThreadRun() } } - if (__predict_true(utf8str.empty() == false)) { - DoLog(utf8str); + if (msg.type == LogMsg::Type::Log) { + DoLog(msg.text); + } else { + DoStdout(msg.text); } } } +// 標準出力へ出力。 +void +Logger::DoStdout(const std::string& text) +{ + fputs(text.c_str(), stdout); + fflush(stdout); +} + // 着信処理。 void Logger::DoLog(const std::string& utf8str) { - // 必要なら標準出力にも出力 if (use_stdout) { + // 標準出力にも出力。 + // 入力のログ文字列に終端の改行はなく、 + // puts() は stdout に改行を付けて出す。fflush() は念のためくらい。 puts(utf8str.c_str()); + fflush(stdout); } // コンバータがなければここで終了 (CLI)。 @@ -289,7 +351,7 @@ Logger::ResizeCol(int newcol) // userdata = 1 なら1行古いほうに遡った状態、となる。 // screen.userdata + screen の行数が maxlines を超えてはいけない。 void -Logger::MonitorUpdate(Monitor *, TextScreen& screen) +Logger::MonitorScreen(Monitor *, TextScreen& screen) { assertmsg(screen.userdata + screen.GetRow() <= maxlines, "userdata=%" PRIu64 " row=%d maxlines=%d",