OXYGENHUB
◆ main openmsx / src / Reactor.hh
8.5 KiB · C++ · last changed chore(): initial commit 1 month ago source blame history raw
1
#ifndef REACTOR_HH
2
#define REACTOR_HH
3
4
#include "EnumSetting.hh"
5
#include "EventListener.hh"
6
#include "StringSetting.hh"
7
8
#include "Observer.hh"
9
10
#include <cassert>
11
#include <memory>
12
#include <mutex>
13
#include <ranges>
14
#include <string>
15
#include <string_view>
16
#include <vector>
17
18
namespace openmsx {
19
20
class ActivateMachineCommand;
21
class AfterCommand;
22
class AviRecorder;
23
class CliComm;
24
class CommandController;
25
class CommandLineParser;
26
class ConfigInfo;
27
class CreateMachineCommand;
28
class DeleteMachineCommand;
29
class DiskChanger;
30
class DiskFactory;
31
class DiskManipulator;
32
class Display;
33
class EventDistributor;
34
class ExitCommand;
35
class FilePool;
36
class GetClipboardCommand;
37
class GlobalCliComm;
38
class GlobalCommandController;
39
class GlobalSettings;
40
class HotKey;
41
class ImGuiManager;
42
class InfoCommand;
43
class InputEventGenerator;
44
class Interpreter;
45
class ListMachinesCommand;
46
class SetupCommand;
47
class MSXMotherBoard;
48
class MachineCommand;
49
class MessageCommand;
50
class Mixer;
51
class MsxChar2Unicode;
52
class RTScheduler;
53
class RealTimeInfo;
54
class RestoreMachineCommand;
55
class RomDatabase;
56
class SetClipboardCommand;
57
class Setting;
58
class Shortcuts;
59
class SoftwareInfoTopic;
60
class StoreMachineCommand;
61
class SymbolManager;
62
class TclCallbackMessages;
63
class TestMachineCommand;
64
class UserSettings;
65
66
extern int exitCode;
67
68
enum class SetupDepth : uint8_t;
69
70
/**
71
 * Contains the main loop of openMSX.
72
 * openMSX is almost single threaded: the main thread does most of the work,
73
 * we create additional threads only if we need blocking calls for
74
 * communicating with peripherals.
75
 * This class serializes all incoming requests so they can be handled by the
76
 * main thread.
77
 */
78
class Reactor final : private Observer<Setting>, private EventListener
79
{
80
public:
81
	static constexpr std::string_view SETUP_DIR = "setups";
82
	static constexpr std::string_view SETUP_EXTENSION = ".oms";
83
84
public:
85
	Reactor();
86
	void init();
87
	~Reactor();
88
89
	void runStartupScripts(const CommandLineParser& parser);
90
	void powerOn();
91
	void run();
92
93
	void enterMainLoop();
94
95
	[[nodiscard]] Shortcuts& getShortcuts() { return *shortcuts; }
96
	[[nodiscard]] RTScheduler& getRTScheduler() { return *rtScheduler; }
97
	[[nodiscard]] EventDistributor& getEventDistributor() { return *eventDistributor; }
98
	[[nodiscard]] GlobalCliComm& getGlobalCliComm() { return *globalCliComm; }
99
	[[nodiscard]] GlobalCommandController& getGlobalCommandController() { return *globalCommandController; }
100
	[[nodiscard]] InputEventGenerator& getInputEventGenerator() { return *inputEventGenerator; }
101
	[[nodiscard]] Display& getDisplay() { assert(display); return *display; }
102
	[[nodiscard]] Mixer& getMixer();
103
	[[nodiscard]] DiskFactory& getDiskFactory() { return *diskFactory; }
104
	[[nodiscard]] DiskManipulator& getDiskManipulator() { return *diskManipulator; }
105
	[[nodiscard]] EnumSetting<int>& getDefaultMachineSetting() { return *defaultMachineSetting; }
106
	[[nodiscard]] StringSetting& getDefaultSetupSetting() { return *defaultSetupSetting; }
107
	[[nodiscard]] StringSetting& getSaveSetupAtExitNameSetting() { return *saveSetupAtExitNameSetting; }
108
	[[nodiscard]] EnumSetting<SetupDepth>& getSaveSetupAtExitDepthSetting() { return *saveSetupAtExitDepthSetting; }
109
	[[nodiscard]] FilePool& getFilePool() { return *filePool; }
110
	[[nodiscard]] ImGuiManager& getImGuiManager() { return *imGuiManager; }
111
	[[nodiscard]] const HotKey& getHotKey() const;
112
	[[nodiscard]] SymbolManager& getSymbolManager() const { return *symbolManager; }
113
	[[nodiscard]] AviRecorder& getRecorder() const { return *aviRecordCommand; }
114
115
	[[nodiscard]] RomDatabase& getSoftwareDatabase();
116
117
	void switchMachine(const std::string& machine);
118
	void switchMachineFromSetup(zstring_view filename);
119
	[[nodiscard]] MSXMotherBoard* getMotherBoard() const;
120
121
	[[nodiscard]] static std::vector<std::string> getHwConfigs(std::string_view type);
122
	[[nodiscard]] static std::vector<std::string> getSetups();
123
124
	[[nodiscard]] const MsxChar2Unicode& getMsxChar2Unicode() const;
125
126
	void block();
127
	void unblock();
128
129
	// convenience methods
130
	[[nodiscard]] GlobalSettings& getGlobalSettings() { return *globalSettings; }
131
	[[nodiscard]] InfoCommand& getOpenMSXInfoCommand();
132
	[[nodiscard]] CommandController& getCommandController();
133
	[[nodiscard]] CliComm& getCliComm();
134
	[[nodiscard]] Interpreter& getInterpreter();
135
	[[nodiscard]] std::string_view getMachineID() const;
136
137
	using Board = std::shared_ptr<MSXMotherBoard>;
138
	[[nodiscard]] Board createEmptyMotherBoard();
139
	void replaceBoard(MSXMotherBoard& oldBoard, Board newBoard); // for reverse
140
	[[nodiscard]] Board getMachine(std::string_view machineID) const;
141
142
	[[nodiscard]] bool isFullyStarted() const { return fullyStarted; }
143
144
	[[nodiscard]] auto getMachineIDs() const {
145
		return std::views::transform(boards,
146
			[](auto& b) -> std::string_view { return b->getMachineID(); });
147
	}
148
private:
149
	void createDefaultMachineAndSetupSettings();
150
	void switchBoard(Board newBoard);
151
	void deleteBoard(Board board);
152
153
	// Observer<Setting>
154
	void update(const Setting& setting) noexcept override;
155
156
	// EventListener
157
	bool signalEvent(const Event& event) override;
158
159
	void unpause();
160
	void pause();
161
162
private:
163
	std::mutex mbMutex; // this should come first, because it's still used by
164
	                    // the destructors of the unique_ptr below
165
166
	// note: order of unique_ptr's is important
167
	std::unique_ptr<Shortcuts> shortcuts; // before globalCommandController
168
	std::unique_ptr<RTScheduler> rtScheduler;
169
	std::unique_ptr<EventDistributor> eventDistributor;
170
	std::unique_ptr<GlobalCliComm> globalCliComm;
171
	std::unique_ptr<GlobalCommandController> globalCommandController;
172
	std::unique_ptr<GlobalSettings> globalSettings;
173
	std::unique_ptr<InputEventGenerator> inputEventGenerator;
174
	std::unique_ptr<SymbolManager> symbolManager; // before imGuiManager
175
	std::unique_ptr<ImGuiManager> imGuiManager; // before display
176
	std::unique_ptr<Display> display;
177
	std::unique_ptr<Mixer> mixer; // lazy initialized
178
	std::unique_ptr<DiskFactory> diskFactory;
179
	std::unique_ptr<DiskManipulator> diskManipulator;
180
	std::unique_ptr<DiskChanger> virtualDrive;
181
	std::unique_ptr<FilePool> filePool;
182
183
	std::unique_ptr<EnumSetting<int>> defaultMachineSetting;
184
	std::unique_ptr<StringSetting> defaultSetupSetting;
185
	std::unique_ptr<StringSetting> saveSetupAtExitNameSetting;
186
	std::unique_ptr<EnumSetting<SetupDepth>> saveSetupAtExitDepthSetting;
187
	std::unique_ptr<UserSettings> userSettings;
188
	std::unique_ptr<RomDatabase> softwareDatabase; // lazy initialized
189
190
	std::unique_ptr<AfterCommand> afterCommand;
191
	std::unique_ptr<ExitCommand> exitCommand;
192
	std::unique_ptr<MessageCommand> messageCommand;
193
	std::unique_ptr<MachineCommand> machineCommand;
194
	std::unique_ptr<TestMachineCommand> testMachineCommand;
195
	std::unique_ptr<CreateMachineCommand> createMachineCommand;
196
	std::unique_ptr<DeleteMachineCommand> deleteMachineCommand;
197
	std::unique_ptr<ListMachinesCommand> listMachinesCommand;
198
	std::unique_ptr<ActivateMachineCommand> activateMachineCommand;
199
	std::unique_ptr<StoreMachineCommand> storeMachineCommand;
200
	std::unique_ptr<RestoreMachineCommand> restoreMachineCommand;
201
	std::unique_ptr<SetupCommand> setupCommand;
202
	std::unique_ptr<GetClipboardCommand> getClipboardCommand;
203
	std::unique_ptr<SetClipboardCommand> setClipboardCommand;
204
	std::unique_ptr<AviRecorder> aviRecordCommand;
205
	std::unique_ptr<ConfigInfo> extensionInfo;
206
	std::unique_ptr<ConfigInfo> machineInfo;
207
	std::unique_ptr<RealTimeInfo> realTimeInfo;
208
	std::unique_ptr<SoftwareInfoTopic> softwareInfoTopic;
209
	std::unique_ptr<TclCallbackMessages> tclCallbackMessages;
210
211
	// Locking rules for activeBoard access:
212
	//  - main thread can always access activeBoard without taking a lock
213
	//  - changing activeBoard handle can only be done in the main thread
214
	//    and needs to take the mbMutex lock
215
	//  - non-main thread can only access activeBoard via specific
216
	//    member functions (atm only via enterMainLoop()), it needs to take
217
	//    the mbMutex lock
218
	std::vector<Board> boards; // unordered
219
	Board activeBoard; // either nullptr or a board inside 'boards'
220
221
	int blockedCounter = 0;
222
	bool paused = false;
223
	bool fullyStarted = false; // all start up actions completed
224
225
	/**
226
	 * True iff the Reactor should keep running.
227
	 * When this is set to false, the Reactor will end the main loop after
228
	 * finishing the pending request(s).
229
	 */
230
	bool running = true;
231
232
	bool isInit = false; // has the init() method been run successfully
233
234
	friend class MachineCommand;
235
	friend class TestMachineCommand;
236
	friend class CreateMachineCommand;
237
	friend class DeleteMachineCommand;
238
	friend class ListMachinesCommand;
239
	friend class ActivateMachineCommand;
240
	friend class StoreMachineCommand;
241
	friend class RestoreMachineCommand;
242
	friend class SetupCommand;
243
};
244
245
} // namespace openmsx
246
247
#endif // REACTOR_HH