--- nono/vm/event.h 2026/04/29 17:04:28 1.1.1.1 +++ nono/vm/event.h 2026/04/29 17:06:00 1.1.1.13 @@ -1,76 +1,109 @@ // // nono -// Copyright (C) 2018 isaki@NetBSD.org +// Copyright (C) 2020 nono project +// Licensed under nono-license.txt +// + +// +// イベント // #pragma once #include "device.h" -#include -#include - -// ユーザ定義リテラルを使ったサフィックス -// マイクロ秒 -static inline uint64 operator"" _usec(unsigned long long us) -{ - return us * 1000; -} -static inline uint64 operator"" _usec(long double us) -{ - return us * 1000; +template +EventCallback_t ToEventCallback(T f) { + return static_cast(f); } -// ミリ秒 -static inline uint64 operator"" _msec(unsigned long long ms) -{ - return ms * 1000_usec; -} -static inline uint64 operator"" _msec(long double ms) -{ - return ms * 1000_usec; -} - -// 秒 -static inline uint64 operator"" _sec(unsigned long long sec) -{ - return sec * 1000_msec; -} -static inline uint64 operator"" _sec(long double sec) -{ - return sec * 1000_msec; -} - -// コールバック関数の型 -typedef void (Device::*DeviceCallback_t)(int); // イベント // // イベントは必要なデバイスごとに用意する。おそらく最初から個数が決まって // いることが多いはずなので、デバイスクラス内のメンバ変数(実体) として // 宣言し、デバイスのコンストラクタ等で初期化するという流れになるはず。 +// +// VM リセットによるイベントタイマーの停止処理は各デバイスの責任で行うこと。 class Event { public: - Event(); - virtual ~Event(); + Event(Device *, int code_, EventCallback_t, const std::string&); + ~Event(); + + // このイベントが動作中なら true を返す + bool IsRunning() const { + return active; + } + + Device *GetOwner() const noexcept { return dev; } + EventCallback_t GetCallback() const noexcept { return func; } // 以下はイベントを呼び出す側がセットする - // イベントを起こすまでの期間 [nsec] + // コールバック関数をセットする。 + template + void SetCallback(void (T::*func_)(Event *)) { + func = static_cast(func_); + } + + // イベントを起こすまでの仮想時刻での相対時間 [nsec] // 例えば今から 1msec 後にイベントを起こしたい場合は 1000000 となる。 - // ここは MPU クロックサイクルではなく仮想時間で指定する。 - uint64 time = 0; + uint64 time {}; - Device *dev = NULL; // デバイス - DeviceCallback_t func = NULL; // コールバック関数 - int code = 0; // コールバック関数への引数 - std::string name {}; // イベント名(表示用) 最大15文字 + int code {}; // コールバック関数への引数 + const std::string GetName() const { return name; } + void SetName(const std::string& val); // スケジューラが内部で使う - bool active = false; // スケジューラにセットされていれば真 - uint64 cycle = 0; // イベントを起こす仮想サイクル + bool active {}; // スケジューラにセットされていれば真 + uint64 vtime {}; // イベントを起こす仮想時刻 + + uint64 count {}; // コールバックを呼び出した回数 + uint64 last_count {}; // (表示用)前回表示したときの count + + private: + Device *dev {}; // デバイス + EventCallback_t func {}; // コールバック関数 + + // イベント名(表示用) + // '\0' 含まず25文字まで。デバイス名も必要なら含めること。 + std::string name {}; +}; + +// +// イベントマネージャ +// +class EventManager : public Object +{ + using inherited = Object; + friend class Scheduler; + public: + EventManager(); + ~EventManager() override; + + // イベントを登録する。 + Event *Regist(Device *d) { + return Regist(d, 0); + } + Event *Regist(Device *d, EventCallback_t f) { + return Regist(d, 0, f); + } + Event *Regist(Device *d, EventCallback_t f, const std::string& n) { + return Regist(d, 0, f, n); + } + Event *Regist(Device *d, int code) { + return Regist(d, code, NULL); + } + Event *Regist(Device *d, int code, EventCallback_t f) { + return Regist(d, code, f, ""); + } + Event *Regist(Device *d, int code, EventCallback_t f, const std::string& n); + + private: + std::vector all {}; }; -// 全イベントの配列 (scheduler.h にある有効イベントリストとは違うので注意) -extern std::vector gEvents; +inline EventManager* GetEventManager() { + return Object::GetObject(OBJ_EVENT_MANAGER); +}