--- nono/cli/cuimessage.cpp 2026/04/29 17:04:56 1.1.1.1 +++ nono/cli/cuimessage.cpp 2026/04/29 17:05:27 1.1.1.3 @@ -4,10 +4,19 @@ // Licensed under nono-license.txt // +// +// UI スレッドへのメッセージ機構 (CLI 側) +// + +#include "nono.h" #include "cuimessage.h" +#include "kevent.h" std::array CUIMessage::func_table; +/*static*/ autofd CUIMessage::wpipe; +/*static*/ autofd CUIMessage::rpipe; + // UIMessage を func に接続する /*static*/ void CUIMessage::Connect(UIMessage::ID id, CUIMessage::Func func) @@ -15,6 +24,37 @@ CUIMessage::Connect(UIMessage::ID id, CU func_table[id] = func; } +// CUIMessage の初期化。パイプを用意して kqueue ディスクリプタを返す。 +int +CUIMessage::Init() +{ + int kq; + int fds[2]; + + kq = kqueue(); + if (kq < 0) { + warn("CUIMessage::Init: kqueue"); + return -1; + } + + if (pipe(fds) < 0) { + warn("CUIMessage::Init: pipe"); + close(kq); + return -1; + } + + rpipe = fds[0]; + wpipe = fds[1]; + + if (kevent_add(kq, rpipe, EVFILT_READ, EV_ADD, 0) < 0) { + warn("CUIMessage::Init: kevent_add"); + close(kq); + return -1; + } + + return kq; +} + // UIMessage を処理する /*static*/ void CUIMessage::Process(UIMessage::Queue& queue) @@ -23,12 +63,31 @@ CUIMessage::Process(UIMessage::Queue& qu while (queue.Dequeue(&m)) { UIMessage::ID id = m.GetID(); - if (id < 0 || id >= UIMessage::ID_MAX) { - PANIC("Invalid UIMessage %d", id); + + if (id >= UIMessage::ID_MAX) { + PANIC("Invalid UIMessage %u", id); + } + + // パイプで通知。クラス(構造体)をそのまま書き込む。 + int r; + r = write(wpipe, &m, sizeof(m)); + if (r < 0) { + warn("CUIMessage::Process: write"); + continue; } - auto func = func_table[id]; - if (func) { - func(m); + if (r < sizeof(m)) { + warnx("CUIMessage::Process: write: too short"); + continue; } } } + +// UIMessage をディスパッチする (メインスレッドで呼ばれる) +/*static*/ void +CUIMessage::Dispatch(const UIMessage& m) +{ + auto func = func_table[m.GetID()]; + if (func) { + func(m); + } +}