diff options
| author | Felix Morgner <felix.morgner@ost.ch> | 2026-07-26 13:23:46 +0200 |
|---|---|---|
| committer | Felix Morgner <felix.morgner@ost.ch> | 2026-07-26 13:23:46 +0200 |
| commit | 4cc05543d48a35908b0756e133bd668745bd95c3 (patch) | |
| tree | e72c2f5e9e11120ca11837aa43caac47ef571af9 | |
| parent | 5a5fefba28a52feffadf2b810b2f935934aa7b0b (diff) | |
| download | kernel-4cc05543d48a35908b0756e133bd668745bd95c3.tar.xz kernel-4cc05543d48a35908b0756e133bd668745bd95c3.zip | |
kapi: implement device removal
| -rw-r--r-- | kapi/kapi/devices/device_registry.hpp | 30 | ||||
| -rw-r--r-- | kernel/kapi/devices/device_registry.cpp | 82 |
2 files changed, 106 insertions, 6 deletions
diff --git a/kapi/kapi/devices/device_registry.hpp b/kapi/kapi/devices/device_registry.hpp index 3952db66..a65bd4ad 100644 --- a/kapi/kapi/devices/device_registry.hpp +++ b/kapi/kapi/devices/device_registry.hpp @@ -18,12 +18,36 @@ namespace kapi::devices //! @addtogroup kapi-devices-kernel-defined //! @{ + //! The interface for types interested in being notified about changes in the device registry. + struct device_registry_observer + { + //! Enable correct destruction through base pointers. + virtual ~device_registry_observer() = default; + + //! Called after a device has been added to the registry. + //! + //! @param device The device that was added. + virtual auto on_device_added(kstd::shared_ptr<device> const & device) -> void = 0; + + //! Called after a device has been removed from the registry. + //! + //! @param device The device that was remove. + virtual auto on_device_removed(device & device) -> void = 0; + }; + + //! @} + + //! @addtogroup kapi-devices-kernel-defined + //! @{ + struct device_registry { device_registry() = default; + //! Initialize the global singleton registry instance. auto static init() -> void; + //! Get the global singleton registry instance. auto static get() -> device_registry &; //! Add a new device to the kernel's device registry. @@ -49,8 +73,14 @@ namespace kapi::devices //! @return every device current reachable through the registry. [[nodiscard]] auto all() const -> kstd::vector<kstd::shared_ptr<device>>; + //! Subscribe to device registry notifications. + //! + //! @param observer The observer to notify. + auto subscribe(kstd::weak_ptr<device_registry_observer> observer) -> void; + private: kstd::flat_map<kstd::string, kstd::weak_ptr<device>> m_devices{}; + kstd::vector<kstd::weak_ptr<device_registry_observer>> m_observers{}; }; //! @} diff --git a/kernel/kapi/devices/device_registry.cpp b/kernel/kapi/devices/device_registry.cpp index aca0e7fe..f5c20a6d 100644 --- a/kernel/kapi/devices/device_registry.cpp +++ b/kernel/kapi/devices/device_registry.cpp @@ -49,29 +49,89 @@ namespace kapi::devices kstd::println("[OS:DEV] Registering device {}", device->name()); + auto added = false; + + // TODO: lock the registry auto found = m_devices.find(device->name()); if (found != m_devices.end()) { if (!found->second.expired()) { - return false; + added = false; } found->second = device; - return true; + added = true; + } + else + { + added = m_devices.emplace(device->name(), device).second; + } + // TODO: unlock registry + + if (!added) + { + return false; } - return m_devices.emplace(device->name(), device).second; + // TODO: consider if we need to lock the registry observers here, since somebody may add an observer in the meantime + // once multiple codepaths can run at the same time. + for (auto const & observer : m_observers) + { + if (auto locked_observer = observer.lock()) + { + locked_observer->on_device_added(device); + } + } + + // TODO: lock registry + erase_if(m_observers, [](auto const & observer) { return observer.expired(); }); + // TODO: unlock registry + + return true; } - auto device_registry::remove(device &) -> bool + auto device_registry::remove(device & device) -> bool { - kstd::println("[OS:DEV] TODO: implement device deregistration"); - return false; + // TODO: lock registry + + 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<struct device>{}; + + // TODO: unlock registry + + kstd::println("[OS:DEV] Unregistering device {}", device.name()); + + for (auto const & observer : m_observers) + { + if (auto locked_observer = observer.lock()) + { + locked_observer->on_device_removed(device); + } + } + + // TODO: lock registry + erase_if(m_observers, [](auto const & observer) { return observer.expired(); }); + // TODO: unlock registry + + return true; } auto device_registry::find(std::string_view name) const -> kstd::shared_ptr<device> { + // TODO: lock registry + auto found = m_devices.find(kstd::string{name}); if (found == m_devices.end()) { @@ -83,6 +143,8 @@ namespace kapi::devices auto device_registry::all() const -> kstd::vector<kstd::shared_ptr<device>> { + // TODO: lock registry + auto result = kstd::vector<kstd::shared_ptr<device>>{}; for (auto const & [name, weak_device] : m_devices) @@ -95,6 +157,14 @@ namespace kapi::devices return result; } + + auto device_registry::subscribe(kstd::weak_ptr<device_registry_observer> observer) -> void + { + // TODO: lock registry + + erase_if(m_observers, [](auto const & observer) { return observer.expired(); }); + m_observers.push_back(observer); + } } // namespace kapi::devices namespace kapi::test_support::devices |
