--- nono/vm/scheduler.cpp 2026/04/29 17:05:46 1.1.1.20 +++ nono/vm/scheduler.cpp 2026/04/29 17:05:51 1.1.1.21 @@ -31,6 +31,7 @@ // 経過時間との比で求める。同期走行/高速走行の影響は受けない。 #include "scheduler.h" +#include "event.h" #include "monitor.h" #include "rtc.h" #include "syncer.h" @@ -55,95 +56,6 @@ static uint64 ct_pslow; #define CT(name) #endif -#define FORMAT_FULL 0 -#define FORMAT_SEC 1 - -// 経過時間 t を文字列にして返す。 -// 文字列長は、t の大きさ(とフォーマット指定)によって以下の通り。 -// -// 0 1 2 -// 01234567890123456789012345 -// "0.mmm'uuu'nnn" 10秒未満、または FORMAT_SEC なら13桁 -// "59.mmm'uuu'nnn" 1分未満なら14桁 -// " 9:59.mmm'uuu'nnn" 1時間未満なら17桁 -// " 9:59:59.mmm'uuu'nnn" 24時間未満なら20桁 -// "999d 23:59:59.mmm'uuu'nnn" 1日以上なら25桁。これが最大幅。 -// -// FORMAT_SEC は1桁秒以下の場合 (実際には1秒未満の場合) に用いる。 -// FORMAT_FULL は 1000日経過すると桁がずれるけど、それはもういいだろう。 -// -// 10秒未満の場合だけ %2u ではなく %u で1桁切り詰めているが、これは -// FORMAT_SEC との互換性のため。その必要のない10分未満と10時間未満は -// どちらも %2u で表記し桁数を維持することに努める。 -static const std::string -TimeToStrF(uint64 t, int format) -{ - char buf[32]; - char *p; - size_t len; - int n; - - uint ns = t % 1000; - t /= 1000; - uint us = t % 1000; - t /= 1000; - uint ms = t % 1000; - t /= 1000; - - uint s, m, h, d; - if (format == FORMAT_FULL) { - s = t % 60; - t /= 60; - m = t % 60; - t /= 60; - h = t % 24; - t /= 24; - d = t; - } else { - s = t; - m = 0; - h = 0; - d = 0; - } - - p = buf; - len = sizeof(buf); - if (d) { - n = snprintf(p, len, "%3ud %02u:%02u:%02u", d, h, m, s); - p += n; - len -= n; - } else if (h) { - n = snprintf(p, len, "%2u:%02u:%02u", h, m, s); - p += n; - len -= n; - } else if (m) { - n = snprintf(p, len, "%2u:%02u", m, s); - p += n; - len -= n; - } else { - n = snprintf(p, len, "%u", s); - p += n; - len -= n; - } - n = snprintf(p, len, ".%03u'%03u'%03u", ms, us, ns); - p += n; - len -= n; - - return std::string(buf, p - buf); -} - -const std::string -TimeToStr(uint64 t) -{ - return TimeToStrF(t, FORMAT_FULL); -} - -const std::string -SecToStr(uint64 t) -{ - return TimeToStrF(t, FORMAT_SEC); -} - // // スケジューラ // @@ -175,6 +87,7 @@ Scheduler::~Scheduler() bool Scheduler::Init() { + evman = GetEventManager(); syncer = GetSyncer(); return true; @@ -185,7 +98,7 @@ bool Scheduler::Init2() { // イベントの個数が確定した(してなければならない) - monitor->AddHeight(all_events.size()); + monitor->AddHeight(evman->all.size()); return true; } @@ -243,7 +156,7 @@ Scheduler::ThreadRun() // コールバック ev->count++; - ((ev->dev)->*(ev->func))(*ev); + ((ev->dev)->*(ev->func))(ev); } } @@ -252,9 +165,9 @@ void Scheduler::StartTime() { // イベントキューを空にする - for (auto ev : all_events) { + for (auto *ev : evman->all) { if (ev->active) { - StopEvent(*ev); + StopEvent(ev); } ev->count = 0; } @@ -271,31 +184,19 @@ Scheduler::StartTime() void Scheduler::Terminate() { - std::unique_lock lock(mtx); + std::lock_guard lock(mtx); request |= REQUEST_EXIT; cv.notify_one(); } -// イベントを登録する。 -// 登録時点では実は type だけ確定していればよい。 -// -// ここで管理してるのはポインタだけで、実体は呼び出し元クラスのメンバ -// インスタンスのはずなので、登録しっぱなしにする。 -void -Scheduler::RegistEvent(Event& ev) -{ - // イベントリストに追加 - all_events.push_back(&ev); -} - // 指定のイベントを開始する。 // すでに同イベントが登録されている場合は古いイベントを削除してから // 新しいイベントを再登録となる。 // イベントはワンショットのみ。 void -Scheduler::RestartEvent(Event& ev) +Scheduler::RestartEvent(Event *ev) { - if (ev.IsRunning()) { + if (ev->IsRunning()) { StopEvent(ev); } @@ -306,7 +207,7 @@ Scheduler::RestartEvent(Event& ev) // このイベントが登録されてないことが確定できる場合のみこちらが使える。 // イベントはワンショットのみ。 void -Scheduler::StartEvent(Event& ev) +Scheduler::StartEvent(Event *ev) { CT(start); #ifdef CT_ON @@ -325,22 +226,22 @@ Scheduler::StartEvent(Event& ev) #endif // この assert を有効にすると 10 ポイント性能が低下する(502%->492%) - //assertmsg(ev.IsRunning() == false, "%s", ev.GetName().c_str()); + //assertmsg(ev->IsRunning() == false, "%s", ev->GetName().c_str()); // vtime は仮想絶対時刻 [nsec]、time は仮想相対時間 [nsec] - ev.vtime = vtime + ev.time; + ev->vtime = vtime + ev->time; - ev.active = true; + ev->active = true; - if (__predict_true(ev.vtime <= slow_top_vtime)) { + if (__predict_true(ev->vtime <= slow_top_vtime)) { if (__predict_true(fast == NULL)) { CT(start1); - fast = &ev; + fast = ev; } else { - if (__predict_false(ev.vtime <= fast->vtime)) { + if (__predict_false(ev->vtime <= fast->vtime)) { CT(start2); - PushSlow(*fast); - fast = &ev; + PushSlow(fast); + fast = ev; } else { CT(start3); PushSlow(ev); @@ -356,7 +257,7 @@ Scheduler::StartEvent(Event& ev) // rt_now はイベント発行者の実時間での現在時刻で、 // rt_period は次回のイベントまでの実時間間隔。 void -Scheduler::StartRealtimeEvent(Event& ev, uint64 rt_now, uint64 rt_period) +Scheduler::StartRealtimeEvent(Event *ev, uint64 rt_now, uint64 rt_period) { // 実時間をもとに仮想時間軸上の推定を行う。 @@ -368,16 +269,16 @@ Scheduler::StartRealtimeEvent(Event& ev, // 周期を短くして回復運転させる。 // 周期を短くしすぎるとゲストが処理できなくなるので、 // 10% カットに留める。 - ev.time = rt_period - rt_period / 10; + ev->time = rt_period - rt_period / 10; } else if (rtime < rt_now - rt_period) { // イベントがさらに 1 period 以上進んでいる。 // 実時間を追い越してしまっているので、イベントの // 周期を長くして待つ。長くする方はいくらでも長くしていいので、 // 連続した場合はどんどん長くしていく。 - ev.time += rt_period; + ev->time += rt_period; } else { // おおむね同期している - ev.time = rt_period; + ev->time = rt_period; } RestartEvent(ev); @@ -385,7 +286,7 @@ Scheduler::StartRealtimeEvent(Event& ev, // ev は slow_top には来ない前提 void -Scheduler::EnqueueSlow(Event& ev) +Scheduler::EnqueueSlow(Event *ev) { CT(eslow); @@ -393,33 +294,33 @@ Scheduler::EnqueueSlow(Event& ev) slow[++slow_top] = slow[s]; for (; --s >= 0; ) { - if (ev.vtime <= slow[s]->vtime) { - slow[s + 1] = &ev; + if (ev->vtime <= slow[s]->vtime) { + slow[s + 1] = ev; return; } else { slow[s + 1] = slow[s]; } } - slow[0] = &ev; + slow[0] = ev; } void -Scheduler::PushSlow(Event& ev) +Scheduler::PushSlow(Event *ev) { CT(pslow); - slow[++slow_top] = &ev; - slow_top_vtime = ev.vtime; + slow[++slow_top] = ev; + slow_top_vtime = ev->vtime; } // 指定のイベントを停止する。 // 指定されたイベントが登録されていなければ何もしない。 void -Scheduler::StopEvent(Event& ev) +Scheduler::StopEvent(Event *ev) { - ev.active = false; + ev->active = false; - if (__predict_false(&ev == fast)) { + if (__predict_false(ev == fast)) { CT(stop1); fast = NULL; } else { @@ -429,14 +330,14 @@ Scheduler::StopEvent(Event& ev) } void -Scheduler::StopSlowEvent(Event& ev) +Scheduler::StopSlowEvent(Event *ev) { CT(sslow); int s = slow_top; for (; s >= 0; s--) { - if (&ev == slow[s]) { + if (ev == slow[s]) { for (; s < slow_top; s++) { slow[s] = slow[s + 1]; } @@ -503,7 +404,7 @@ Scheduler::InvokeMessage(MessageID msgid void Scheduler::SendMessage(MessageID msgid, uint32 arg) { - std::unique_lock lock(mtx); + std::lock_guard lock(mtx); if (msgid < MessageID::MAX_REQUEST) { request |= 1U << (uint)msgid; @@ -554,7 +455,7 @@ Scheduler::MonitorUpdate(Monitor *, Text screen.Puts(75, y, "Count"); y++; - for (const auto ev : all_events) { + for (auto *ev : evman->all) { uint64 rem; TA attr;