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