diff options
| author | Felix Morgner <felix.morgner@ost.ch> | 2026-07-25 11:25:59 +0200 |
|---|---|---|
| committer | Felix Morgner <felix.morgner@ost.ch> | 2026-07-25 11:29:44 +0200 |
| commit | 9c6f14583169100b7cd70346c7dc3d13d82806aa (patch) | |
| tree | a562a0c6b283573e989ef4162ffe32a9ce491b9e /kernel/kapi/devices/interface_registry.cpp | |
| parent | dda6499eb6b718631034a274bba83053e1db8725 (diff) | |
| download | kernel-9c6f14583169100b7cd70346c7dc3d13d82806aa.tar.xz kernel-9c6f14583169100b7cd70346c7dc3d13d82806aa.zip | |
kapi: implement interface registry notifications
Diffstat (limited to 'kernel/kapi/devices/interface_registry.cpp')
| -rw-r--r-- | kernel/kapi/devices/interface_registry.cpp | 96 |
1 files changed, 91 insertions, 5 deletions
diff --git a/kernel/kapi/devices/interface_registry.cpp b/kernel/kapi/devices/interface_registry.cpp index 2ec336ed..1d456b30 100644 --- a/kernel/kapi/devices/interface_registry.cpp +++ b/kernel/kapi/devices/interface_registry.cpp @@ -46,6 +46,8 @@ namespace kapi::devices auto interface_registry::do_publish(kstd::shared_ptr<device> device, kstd::string name, interface_id interface, void * implementation) -> kstd::result<void> { + // TODO: lock registry + erase_if(m_entries, [interface](auto e) { return e.interface() == interface && !e.device(); }); if (!device || !implementation || name.empty()) @@ -53,30 +55,87 @@ namespace kapi::devices return kstd::failure(make_error_code(kstd::errc::invalid_argument)); } - auto published = std::ranges::any_of(m_entries, [&](auto const & entry) { + auto already_published = std::ranges::any_of(m_entries, [&](auto const & entry) { return entry.interface() == interface && entry.device().get() == device.get(); }); - if (published) + if (already_published) { return kstd::failure(make_error_code(kstd::errc::file_exists)); } - m_entries.emplace_back(device, std::move(name), interface, implementation); + auto & published = m_entries.emplace_back(device, std::move(name), interface, implementation); + + do_notify_published(interface, published); return kstd::success(); } - auto interface_registry::unpublish(device const & device, interface_id interface) -> void + auto interface_registry::do_notify_published(interface_id interface, entry const & published) -> void + { + std::ranges::for_each(m_observers, [&](auto observer) { + if (auto locked_observer = observer.lock()) + { + locked_observer->on_interface_published(interface, published); + } + }); + + std::ranges::for_each(m_static_observers, + [&](auto observer) { observer->on_interface_published(interface, published); }); + } + + auto interface_registry::do_notify_withdrawn(interface_id interface, device const & device) -> void + { + std::ranges::for_each(m_observers, [&](auto observer) { + if (auto locked_observer = observer.lock()) + { + locked_observer->on_interface_withdrawn(interface, const_cast<devices::device &>(device)); + } + }); + + std::ranges::for_each(m_static_observers, [&](auto observer) { + observer->on_interface_withdrawn(interface, const_cast<devices::device &>(device)); + }); + } + + auto interface_registry::withdraw(device const & device, interface_id interface) -> void + { + // TODO: lock registry + + auto did_remove = erase_if(m_entries, [&](auto e) { + auto locked_device = e.device(); + return e.interface() == interface && locked_device && locked_device.get() == &device; + }) != 0; + + if (did_remove) + { + do_notify_withdrawn(interface, device); + } + } + + auto interface_registry::withdraw_all_for(device const & device) -> void { + // TODO: lock registry + + auto withdrawn_interfaces = kstd::vector<interface_id>{}; + erase_if(m_entries, [&](auto e) { auto locked_device = e.device(); - return e.interface() == interface && locked_device && locked_device.get() == &device; + auto do_erase = locked_device && locked_device.get() == &device; + if (do_erase) + { + withdrawn_interfaces.push_back(e.interface()); + } + return do_erase; }); + + std::ranges::for_each(withdrawn_interfaces, [&](auto interface) { do_notify_withdrawn(interface, device); }); } auto interface_registry::all(interface_id interface) const -> kstd::vector<entry> { + // TODO: lock registry + auto filtered = m_entries; erase_if(filtered, [&](auto e) { auto locked_device = e.device(); @@ -87,6 +146,8 @@ namespace kapi::devices auto interface_registry::resolve(interface_id interface, std::string_view name) -> void * { + // TODO: lock registry + auto found = std::ranges::find_if(m_entries, [&](auto e) { return e.name() == name && e.device(); }); if (found == m_entries.cend()) @@ -103,6 +164,8 @@ namespace kapi::devices auto interface_registry::resolve(interface_id interface, device & device) -> void * { + // TODO: lock registry + if (auto by_device = device.as(interface)) { return by_device; @@ -121,6 +184,29 @@ namespace kapi::devices return found->implementation(); } + auto interface_registry::subscribe(kstd::weak_ptr<interface_registry_observer> observer) -> void + { + // TODO: lock registry + + erase_if(m_observers, [](auto const & observer) { return observer.expired(); }); + m_observers.push_back(observer); + } + + auto interface_registry::subscribe(interface_registry_observer & observer) -> void + { + // TODO: lock registry + + m_static_observers.push_back(&observer); + } + + auto interface_registry::unsubscribe(interface_registry_observer & observer) -> void + { + // TODO: lock registry + + erase_if(m_observers, [&](auto const & subscribed) { return subscribed.lock().get() == &observer; }); + erase(m_static_observers, &observer); + } + } // namespace kapi::devices namespace kapi::test_support::devices |
