#include #include #include #include #include #include #include #include #include #include #include namespace kapi::devices { namespace { auto constinit instance = std::optional{}; } auto device_registry::init() -> void { if (instance) { system::panic("[OS:DEV] Device registry has already been initialized"); } instance.emplace(); } auto device_registry::get() -> device_registry & { if (!instance) { system::panic("[OS:DEV] Device registry has not been initialized"); } return *instance; } auto device_registry::add(kstd::shared_ptr device) -> bool { if (!device) { return false; } kstd::println("[OS:DEV] Registering device {}", device->name()); auto added = false; { auto guard = kstd::lock_guard{m_lock}; auto found = m_devices.find(device->name()); if (found != m_devices.end()) { if (!found->second.expired()) { added = false; } found->second = device; added = true; } else { added = m_devices.emplace(device->name(), device).second; } } if (!added) { return false; } auto observers = kstd::vector>{}; { auto guard = kstd::lock_guard{m_lock}; observers = m_observers; } for (auto const & observer : observers) { if (auto locked_observer = observer.lock()) { locked_observer->on_device_added(device); } } { auto guard = kstd::lock_guard{m_lock}; erase_if(m_observers, [](auto const & observer) { return observer.expired(); }); } return true; } auto device_registry::remove(device & device) -> bool { { auto guard = kstd::lock_guard{m_lock}; auto found = m_devices.find(device.name()); if (found == m_devices.end()) { return false; } auto locked = found->second.lock(); if (!locked || locked.get() != &device) { return false; } found->second = kstd::weak_ptr{}; } kstd::println("[OS:DEV] Unregistering device {}", device.name()); auto observers = kstd::vector>{}; { auto guard = kstd::lock_guard{m_lock}; observers = m_observers; } for (auto const & observer : observers) { if (auto locked_observer = observer.lock()) { locked_observer->on_device_removed(device); } } { auto guard = kstd::lock_guard{m_lock}; erase_if(m_observers, [](auto const & observer) { return observer.expired(); }); } return true; } auto device_registry::find(std::string_view name) const -> kstd::shared_ptr { auto guard = kstd::lock_guard{m_lock}; auto found = m_devices.find(kstd::string{name}); if (found == m_devices.end()) { return nullptr; } return found->second.lock(); } auto device_registry::all() const -> kstd::vector> { auto guard = kstd::lock_guard{m_lock}; auto result = kstd::vector>{}; for (auto const & [name, weak_device] : m_devices) { if (auto device = weak_device.lock()) { result.push_back(std::move(device)); } } return result; } auto device_registry::subscribe(kstd::weak_ptr observer) -> void { auto guard = kstd::lock_guard{m_lock}; erase_if(m_observers, [](auto const & observer) { return observer.expired(); }); m_observers.push_back(observer); } } // namespace kapi::devices namespace kapi::test_support::devices { auto deinit_device_registry() -> void { kapi::devices::instance.reset(); } } // namespace kapi::test_support::devices