|
|
1.1 root 1: //
2: // nono
1.1.1.4 root 3: // Copyright (C) 2020 nono project
4: // Licensed under nono-license.txt
1.1 root 5: //
6:
1.1.1.8 root 7: //
8: // VM (基本クラス)
9: //
10:
1.1 root 11: #include "vm.h"
1.1.1.9 root 12: #include "debugger.h"
1.1.1.15! root 13: #include "event.h"
1.1.1.3 root 14: #include "mainapp.h"
1.1.1.9 root 15: #include "mainbus.h"
1.1 root 16: #include "scheduler.h"
1.1.1.8 root 17: #include "signalthread.h"
1.1.1.9 root 18: #include "syncer.h"
1.1.1.15! root 19: #include "uimessage.h"
1.1 root 20:
21: // コンストラクタ
1.1.1.11 root 22: VM::VM(const char *vmname_)
1.1 root 23: {
1.1.1.11 root 24: vmname = vmname_;
25: assert(vmname);
26:
1.1.1.8 root 27: // SignalThread は他のスレッドより先に起動する必要があるので、先頭。
1.1.1.15! root 28: // EventManager は Scheduler に必要。
1.1.1.8 root 29: // Scheduler は以降の他のデバイスからのイベント登録を受け付ける必要が
30: // あるためその次。
1.1.1.14 root 31: // Debugger は HostCOM と stdio ドライバが競合した場合に優先したいため
32: // もあって必ず先に配置する必要がある。
1.1.1.8 root 33: NEWDV(SignalThread, new SignalThread());
1.1.1.15! root 34: NEWDV(EventManager, new EventManager());
1.1.1.8 root 35: NEWDV(Scheduler, new Scheduler());
1.1.1.9 root 36: NEWDV(Syncer, new Syncer());
1.1.1.8 root 37: NEWDV(Debugger, new Debugger());
1.1 root 38: }
39:
40: // デストラクタ
41: VM::~VM()
42: {
1.1.1.4 root 43: Dispose();
44: }
45:
46: // 終了
47: void
48: VM::Dispose()
49: {
1.1.1.15! root 50: // (もう止まってるはずだが) 念のため UIMessage の送出を止める。
! 51: gMainApp.GetUIMessage()->StopUIMessage();
! 52:
! 53: // スレッドを止める。
1.1.1.8 root 54: // デバッガスレッドがスケジューラスレッドにアクセスするのでデバッガが先。
55: if ((bool)pDebugger) {
1.1.1.9 root 56: GetDebugger()->TerminateThread();
1.1.1.8 root 57: }
58: if ((bool)pScheduler) {
1.1.1.9 root 59: GetScheduler()->TerminateThread();
1.1.1.8 root 60: }
61:
62: // 残りのスレッドを停止
63: for (auto obj : gMainApp.GetObjects()) {
64: auto th = dynamic_cast<ThreadDevice *>(obj);
65: if (th) {
66: th->TerminateThread();
67: }
1.1.1.4 root 68: }
1.1.1.8 root 69:
70: // 作ったときと逆順で解放する
71: if ((bool)pDebugger) {
72: pDebugger.reset();
73: }
74:
75: if ((bool)pScheduler) {
76: pScheduler.reset();
77: }
78:
1.1.1.15! root 79: if ((bool)pEventManager) {
! 80: pEventManager.reset();
! 81: }
! 82:
1.1.1.8 root 83: // ほかのオブジェクトの解放はグローバルデストラクタにおまかせ。
84: // だめだったらまた考える。
1.1 root 85: }
86:
1.1.1.13 root 87: // 動的コンストラクション。
1.1 root 88: bool
1.1.1.13 root 89: VM::Create(VM::CreationPhase phase)
1.1 root 90: {
1.1.1.8 root 91: // d->Create() は Object を追加する場合があるため、ここで
1.1.1.13 root 92: // ranged for は使えない。また追加されたデバイスの Create()/Create2() も
1.1.1.7 root 93: // 実行したいため、ループ終了条件で毎回 size() を取り出して比較する。
1.1.1.8 root 94: for (int i = 0; i < gMainApp.GetObjects().size(); i++) {
95: auto dev = dynamic_cast<Device *>(gMainApp.GetObjects()[i]);
96: if (dev) {
1.1.1.13 root 97: if (phase == CreationPhase::First) {
98: if (!dev->Create()) {
99: return false;
100: }
101: } else {
102: if (!dev->Create2()) {
103: return false;
104: }
1.1.1.8 root 105: }
1.1 root 106: }
107: }
108:
1.1.1.13 root 109: // ログのためのメンバ変数初期化。
110: // 同じオブジェクトに対して複数回呼んでも副作用はない。
111: for (auto obj : gMainApp.GetObjects()) {
112: auto dev = dynamic_cast<Device *>(obj);
113: if (dev) {
114: dev->EarlyInit();
115: }
116: }
117:
1.1.1.15! root 118: // 名無しオブジェクトがあれば開発中に検出したい。
! 119: // 名無しでも動作には影響ないのでリリース版では怒られないでほしい。
! 120: #if !defined(RELEASE)
! 121: for (auto obj : gMainApp.GetObjects()) {
! 122: if (obj->GetName().empty()) {
! 123: printf("Objects:\n");
! 124: for (auto o : gMainApp.GetObjects()) {
! 125: printf("%s\n", o->GetName().c_str());
! 126: }
! 127: assert(obj->GetName().empty() == false);
! 128: }
! 129: }
! 130: #endif
! 131:
1.1 root 132: return true;
133: }
134:
135: // 初期化
136: bool
137: VM::Init()
138: {
1.1.1.8 root 139: for (auto obj : gMainApp.GetObjects()) {
140: auto dev = dynamic_cast<Device *>(obj);
141: if (dev) {
142: if (!dev->Init()) {
143: return false;
144: }
145: }
146: }
147:
1.1.1.11 root 148: // デバイスの初期化が全部出来たのでメインバスの初期化。
149: auto mainbus = dynamic_cast<MainbusDevice*>(pMainbus.get());
150: if (mainbus->InitMainbus() == false) {
151: return false;
152: }
153:
1.1.1.12 root 154: // イベントが出揃ったのでスケジューラモニタの行数を確定。
155: auto scheduler = dynamic_cast<Scheduler*>(pScheduler.get());
156: if (scheduler->Init2() == false) {
157: return false;
158: }
159:
1.1.1.8 root 160: return true;
161: }
162:
163: // スレッド開始
164: bool
165: VM::StartThread()
166: {
167: for (auto obj : gMainApp.GetObjects()) {
168: auto th = dynamic_cast<ThreadDevice *>(obj);
169: if (th) {
170: if (!th->StartThread()) {
171: return false;
172: }
1.1 root 173: }
174: }
175:
176: return true;
177: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.