File:  [Isaki's NoNo m68k/m88k emulator] / nono / host / logger.h
Revision 1.1.1.3 (vendor branch): download - view: text, annotated - select for diffs
Wed Apr 29 17:06:02 2026 UTC (2 months, 3 weeks ago) by root
Branches: MAIN, Isaki
CVS tags: v027, HEAD
nono 1.7.0

//
// nono
// Copyright (C) 2025 nono project
// Licensed under nono-license.txt
//

//
// ログ
//

#pragma once

#include "thread.h"
#include <condition_variable>
#include <deque>
#include <mutex>
#include <thread>

class TextScreen;

// ログメッセージ構造
class LogMsg
{
 public:
	enum Type {
		Log,
		Stdout,
	};

 public:
	LogMsg() {
	}
	LogMsg(Type type_, const std::string& text_) {
		type = type_;
		text = text_;
	}

	Type type {};
	std::string text {};
};

// ログは世界が出来る前から(全部終わった最後まで)機能していてほしいため、
// ThreadDevice からの継承はしない。
// ログウィンドウ用のモニタを持つために Object を継承しているが、
// ログは出力できない。
class Logger : public Object, public ThreadBase
{
	using inherited = Object;

	// ログの最大行数。modulo するので 2 のべき乗推奨。
	static const uint maxlines = 1024;

	static constexpr uint32 REQ_QUEUE		= 0x00000001;
	static constexpr uint32 REQ_TERMINATE	= 0x80000000;

 public:
	Logger();
	~Logger() override;

	// スレッドを開始する。
	bool StartThread();

	// UTF-8 -> Shift_JIS 変換関数を登録する。
	void SetConverter(std::string (*)(const std::string&));

	// スレッドに終了を要求し、その終了を待つ。
	void TerminateThread();

	// 標準出力にも出すかどうか
	void UseStdout(bool val);

	// ログの表示桁数を変更する。
	bool ResizeCol(int);

	// ログ書き込み。
	void WriteLog(const char *);

	// 標準出力への出力。
	void WriteStdout(const char *);

	// 表示バッファの有効な行数を返す。
	int GetDispLines() const { return displines; }

	Monitor *GetMonitor() const { return monitor; }

 private:
	void OnStart();
	void Terminate();
	void ThreadRun();
	void DoStdout(const std::string&);
	void DoLog(const std::string&);
	void AddLog(const std::string&);
	void AddDisplay(const std::string&);

	DECLARE_MONITOR_SCREEN(MonitorScreen);

	// ログ・標準出力受け付けキュー。
	std::deque<LogMsg> queue {};

	// ログ受け付けキューの条件変数。
	uint32 request {};
	std::mutex queue_mtx {};
	std::condition_variable cv {};

	// 標準出力にも出すかどうか。
	bool use_stdout {};

	// バックログの実体。
	std::deque<std::string> logs {};

	// 表示用に構成した中間バッファ。
	// 横が col 桁 * 高さ maxlines 行の固定長。
	// 行単位のリングバッファとして使う。
	// そのまま表示用になるので、空いてるところは ' '(空白) で埋める。
	std::vector<uint8> dispbuf {};

	// 表示バッファの桁数。
	uint col {};

	// 次に書き込む行 (== 最古の行)。dispbuf の先頭を 0行目と数える。
	int current {};

	// 表示バッファの有効な行数。
	int displines {};

	// UTF-8 -> Shift_JIS 変換関数。(GUI が登録する)
	std::string (*utf8_to_sjis_converter)(const std::string&) {};

	Monitor *monitor {};

	// バックログのロック。
	std::mutex backend_mtx {};

	// スレッド。
	std::unique_ptr<std::thread> thread {};

	// スレッド開始同期用
	std::mutex thread_starter {};
};

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.