dingusppc/machines/machinebase.cpp
Mihai Parparita e5c50640e3 machinebase: fully initialize devices registered by other devices
postinit_devices() may cause additional devices to be registered
(e.g. PCI hosts will register their cards). We were not calling
device_postinit on those devices, because the iterator over the
device map was set up at the start of the loop.

Keep looping until we've actually initialized all devices in the map.
2023-11-08 00:11:41 -08:00

100 lines
3.0 KiB
C++

/*
DingusPPC - The Experimental PowerPC Macintosh emulator
Copyright (C) 2018-22 divingkatae and maximum
(theweirdo) spatium
(Contact divingkatae#1017 or powermax#2286 on Discord for more info)
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#include <devices/common/hwcomponent.h>
#include <loguru.hpp>
#include <machines/machinebase.h>
#include <map>
#include <set>
#include <string>
std::unique_ptr<MachineBase> gMachineObj = 0;
MachineBase::MachineBase(std::string name) {
this->name = name;
/* initialize internal maps */
this->device_map.clear();
}
MachineBase::~MachineBase() {
this->device_map.clear();
}
void MachineBase::add_device(std::string name, std::unique_ptr<HWComponent> dev_obj) {
if (this->device_map.count(name)) {
LOG_F(ERROR, "Device %s already exists!", name.c_str());
return;
}
this->device_map[name] = std::move(dev_obj);
}
HWComponent* MachineBase::get_comp_by_name(std::string name) {
if (this->device_map.count(name)) {
return this->device_map[name].get();
} else {
LOG_F(WARNING, "Component name %s not found!", name.c_str());
return nullptr;
}
}
HWComponent* MachineBase::get_comp_by_type(HWCompType type) {
std::string comp_name;
bool found = false;
for (auto it = this->device_map.begin(); it != this->device_map.end(); it++) {
if (it->second->supports_type(type)) {
comp_name = it->first;
found = true;
break;
}
}
if (found) {
return this->get_comp_by_name(comp_name);
} else {
LOG_F(WARNING, "No component of type %llu was found!", type);
return nullptr;
}
}
int MachineBase::postinit_devices()
{
// Allow additional devices to be registered by device_postinit, in which
// case we'll initialize them too.
std::set<std::string> initialized_devices;
while (initialized_devices.size() < this->device_map.size()) {
for (auto it = this->device_map.begin(); it != this->device_map.end(); it++) {
if (initialized_devices.find(it->first) == initialized_devices.end()) {
if (it->second->device_postinit()) {
LOG_F(ERROR, "Could not initialize device %s", it->first.c_str());
return -1;
}
initialized_devices.insert(it->first);
}
}
}
return 0;
}