aboutsummaryrefslogtreecommitdiff
path: root/kernel/kapi/devices
diff options
context:
space:
mode:
Diffstat (limited to 'kernel/kapi/devices')
-rw-r--r--kernel/kapi/devices/bus.cpp11
-rw-r--r--kernel/kapi/devices/device.cpp14
-rw-r--r--kernel/kapi/devices/driver.cpp2
-rw-r--r--kernel/kapi/devices/driver.tests.cpp78
-rw-r--r--kernel/kapi/devices/driver_registry.cpp2
-rw-r--r--kernel/kapi/devices/driver_registry.tests.cpp21
-rw-r--r--kernel/kapi/devices/facet_registry.cpp216
-rw-r--r--kernel/kapi/devices/facet_registry.tests.cpp (renamed from kernel/kapi/devices/interface_registry.tests.cpp)112
-rw-r--r--kernel/kapi/devices/interface_registry.cpp218
9 files changed, 346 insertions, 328 deletions
diff --git a/kernel/kapi/devices/bus.cpp b/kernel/kapi/devices/bus.cpp
index a9bba4fb..9eecced0 100644
--- a/kernel/kapi/devices/bus.cpp
+++ b/kernel/kapi/devices/bus.cpp
@@ -37,19 +37,14 @@ namespace kapi::devices
return {m_devices.data(), m_devices.size()};
}
- auto bus::protocol() -> struct bus_protocol *
+ auto bus::query_facet(kapi::capabilities::facet_id facet) -> void *
{
- return nullptr;
- }
-
- auto bus::query_interface(interface_id interface) -> void *
- {
- if (interface == bus::id)
+ if (facet == bus::id)
{
return this;
}
- return device::query_interface(interface);
+ return device::query_facet(facet);
}
} // namespace kapi::devices \ No newline at end of file
diff --git a/kernel/kapi/devices/device.cpp b/kernel/kapi/devices/device.cpp
index 01096165..2628e4f4 100644
--- a/kernel/kapi/devices/device.cpp
+++ b/kernel/kapi/devices/device.cpp
@@ -12,19 +12,19 @@ namespace kapi::devices
: m_name(name)
{}
- auto device::as(interface_id interface) noexcept -> void *
+ auto device::facet(kapi::capabilities::facet_id facet) noexcept -> void *
{
- return query_interface(interface);
+ return query_facet(facet);
}
- auto device::as(interface_id interface) const noexcept -> void const *
+ auto device::facet(kapi::capabilities::facet_id facet) const noexcept -> void const *
{
- return const_cast<device *>(this)->query_interface(interface);
+ return const_cast<device *>(this)->query_facet(facet);
}
- auto device::is_a(interface_id interface) const noexcept -> bool
+ auto device::has_facet(kapi::capabilities::facet_id facet) const noexcept -> bool
{
- return const_cast<device *>(this)->query_interface(interface) != nullptr;
+ return const_cast<device *>(this)->query_facet(facet) != nullptr;
}
auto device::name() const -> kstd::string const &
@@ -67,7 +67,7 @@ namespace kapi::devices
m_driver_data = data;
}
- auto device::query_interface(interface_id) -> void *
+ auto device::query_facet(kapi::capabilities::facet_id) -> void *
{
return nullptr;
}
diff --git a/kernel/kapi/devices/driver.cpp b/kernel/kapi/devices/driver.cpp
index be2866f0..55b7507b 100644
--- a/kernel/kapi/devices/driver.cpp
+++ b/kernel/kapi/devices/driver.cpp
@@ -11,7 +11,7 @@ namespace kapi::devices
return std::nullopt;
}
- auto driver::query_interface(interface_id) -> void *
+ auto driver::query_facet(kapi::capabilities::facet_id) -> void *
{
return nullptr;
}
diff --git a/kernel/kapi/devices/driver.tests.cpp b/kernel/kapi/devices/driver.tests.cpp
index e65e48e0..560cc1bc 100644
--- a/kernel/kapi/devices/driver.tests.cpp
+++ b/kernel/kapi/devices/driver.tests.cpp
@@ -16,39 +16,49 @@ namespace
{
struct controller_identification
{
- constexpr auto static id = kapi::devices::interface_id{"stacking_test_controller_identification"};
+ constexpr auto static id = kapi::capabilities::facet_id{"stacking_test_controller_identification"};
virtual ~controller_identification() = default;
[[nodiscard]] virtual auto controller_name() const -> std::string_view = 0;
};
struct controller_driver_identification
{
- constexpr auto static id = kapi::devices::interface_id{"stacking_test_controller_driver_identification"};
+ constexpr auto static id = kapi::capabilities::facet_id{"stacking_test_controller_driver_identification"};
virtual ~controller_driver_identification() = default;
[[nodiscard]] virtual auto supported_names() const -> std::span<std::string_view const> = 0;
};
- struct controller_bus final : kapi::devices::bus, kapi::devices::bus_protocol
+ struct controller_protocol : kapi::devices::bus_protocol
{
- using kapi::devices::bus::bus;
+ constexpr auto static id = kapi::capabilities::facet_id{"stacking_test_controller_protocol"};
auto enumerate(kapi::devices::bus &) -> void override {}
[[nodiscard]] auto match(kapi::devices::device const & dev, kapi::devices::driver const & drv) const
-> kstd::result<std::uint32_t> override
{
- auto const * ident = dev.as<controller_identification>();
- auto const * claims = drv.as<controller_driver_identification>();
+ auto const * ident = dev.facet<controller_identification>();
+ auto const * claims = drv.facet<controller_driver_identification>();
if (!ident || !claims || !std::ranges::contains(claims->supported_names(), ident->controller_name()))
{
return kstd::failure(kapi::devices::driver_match_errc::no_match);
}
return 0u;
}
+ } constinit controller_protocol_instance{};
+
+ struct controller_bus final : kapi::devices::bus
+ {
+ using kapi::devices::bus::bus;
- [[nodiscard]] auto protocol() -> kapi::devices::bus_protocol * override
+ [[nodiscard]] auto query_facet(kapi::capabilities::facet_id id) -> void * override
{
- return this;
+ if (id == controller_protocol::id || id == kapi::devices::bus_protocol::id)
+ {
+ return &controller_protocol_instance;
+ }
+
+ return kapi::devices::bus::query_facet(id);
}
};
@@ -64,26 +74,26 @@ namespace
}
protected:
- auto query_interface(kapi::devices::interface_id interface) -> void * override
+ auto query_facet(kapi::capabilities::facet_id facet) -> void * override
{
- if (interface == controller_identification::id)
+ if (facet == controller_identification::id)
{
return static_cast<controller_identification *>(this);
}
- return kapi::devices::bus::query_interface(interface);
+ return kapi::devices::bus::query_facet(facet);
}
};
struct leaf_identification
{
- constexpr auto static id = kapi::devices::interface_id{"stacking_test_leaf_identification"};
+ constexpr auto static id = kapi::capabilities::facet_id{"stacking_test_leaf_identification"};
virtual ~leaf_identification() = default;
[[nodiscard]] virtual auto leaf_name() const -> std::string_view = 0;
};
struct leaf_driver_identification
{
- constexpr auto static id = kapi::devices::interface_id{"stacking_test_leaf_driver_identification"};
+ constexpr auto static id = kapi::capabilities::facet_id{"stacking_test_leaf_driver_identification"};
virtual ~leaf_driver_identification() = default;
[[nodiscard]] virtual auto supported_names() const -> std::span<std::string_view const> = 0;
};
@@ -100,19 +110,19 @@ namespace
}
protected:
- auto query_interface(kapi::devices::interface_id interface) -> void * override
+ auto query_facet(kapi::capabilities::facet_id facet) -> void * override
{
- if (interface == leaf_identification::id)
+ if (facet == leaf_identification::id)
{
return static_cast<leaf_identification *>(this);
}
- return kapi::devices::device::query_interface(interface);
+ return kapi::devices::device::query_facet(facet);
}
};
- struct leaf_bus final : kapi::devices::bus, kapi::devices::bus_protocol
+ struct leaf_protocol final : kapi::devices::bus_protocol
{
- using kapi::devices::bus::bus;
+ constexpr auto static id = kapi::capabilities::facet_id{"stacking_test_leaf_protocol"};
auto enumerate(kapi::devices::bus & self) -> void override
{
@@ -122,18 +132,28 @@ namespace
[[nodiscard]] auto match(kapi::devices::device const & dev, kapi::devices::driver const & drv) const
-> kstd::result<std::uint32_t> override
{
- auto const * ident = dev.as<leaf_identification>();
- auto const * claims = drv.as<leaf_driver_identification>();
+ auto const * ident = dev.facet<leaf_identification>();
+ auto const * claims = drv.facet<leaf_driver_identification>();
if (!ident || !claims || !std::ranges::contains(claims->supported_names(), ident->leaf_name()))
{
return kstd::failure(kapi::devices::driver_match_errc::no_match);
}
return 0u;
}
+ } constinit leaf_protocol_instance{};
+
+ struct leaf_bus final : kapi::devices::bus
+ {
+ using kapi::devices::bus::bus;
- [[nodiscard]] auto protocol() -> kapi::devices::bus_protocol * override
+ [[nodiscard]] auto query_facet(kapi::capabilities::facet_id id) -> void * override
{
- return this;
+ if (id == leaf_protocol::id || id == kapi::devices::bus_protocol::id)
+ {
+ return &leaf_protocol_instance;
+ }
+
+ return kapi::devices::bus::query_facet(id);
}
};
@@ -144,7 +164,7 @@ namespace
auto self_as_bus = kstd::static_pointer_cast<kapi::devices::bus>(dev.shared_from_this());
auto leaf = kstd::make_shared<leaf_bus>("stacking_test_leaf_bus");
self_as_bus->add_child(leaf);
- leaf->enumerate(*leaf);
+ leaf->facet<leaf_protocol>()->enumerate(*leaf);
return kstd::success();
}
@@ -163,14 +183,14 @@ namespace
}
protected:
- auto query_interface(kapi::devices::interface_id interface) -> void * override
+ auto query_facet(kapi::capabilities::facet_id facet) -> void * override
{
- if (interface == controller_driver_identification::id)
+ if (facet == controller_driver_identification::id)
{
return static_cast<controller_driver_identification *>(this);
}
- return kapi::devices::driver::query_interface(interface);
+ return kapi::devices::driver::query_facet(facet);
}
};
@@ -195,14 +215,14 @@ namespace
}
protected:
- auto query_interface(kapi::devices::interface_id interface) -> void * override
+ auto query_facet(kapi::capabilities::facet_id facet) -> void * override
{
- if (interface == leaf_driver_identification::id)
+ if (facet == leaf_driver_identification::id)
{
return static_cast<leaf_driver_identification *>(this);
}
- return kapi::devices::driver::query_interface(interface);
+ return kapi::devices::driver::query_facet(facet);
}
};
} // namespace
diff --git a/kernel/kapi/devices/driver_registry.cpp b/kernel/kapi/devices/driver_registry.cpp
index cb101d27..842dbc1d 100644
--- a/kernel/kapi/devices/driver_registry.cpp
+++ b/kernel/kapi/devices/driver_registry.cpp
@@ -79,7 +79,7 @@ namespace kapi::devices
}
auto parent = device->parent();
- auto protocol = parent ? parent->protocol() : nullptr;
+ auto protocol = parent ? parent->facet<kapi::devices::bus_protocol>() : nullptr;
if (!protocol)
{
return;
diff --git a/kernel/kapi/devices/driver_registry.tests.cpp b/kernel/kapi/devices/driver_registry.tests.cpp
index d4d8a174..c7d1744d 100644
--- a/kernel/kapi/devices/driver_registry.tests.cpp
+++ b/kernel/kapi/devices/driver_registry.tests.cpp
@@ -15,7 +15,7 @@ namespace
struct test_identification
{
- constexpr auto static id = kapi::devices::interface_id{"test_identification"};
+ constexpr auto static id = kapi::capabilities::facet_id{"test_identification"};
virtual ~test_identification() = default;
@@ -25,6 +25,8 @@ namespace
struct test_protocol final : kapi::devices::bus_protocol
{
+ constexpr auto static id = kapi::capabilities::facet_id{"test_protocol"};
+
explicit test_protocol(unsigned * match_calls)
: match_calls{match_calls}
{}
@@ -36,7 +38,7 @@ namespace
{
++*match_calls;
- auto const * identification = driver.as<test_identification>();
+ auto const * identification = driver.facet<test_identification>();
if (!identification)
{
return kstd::failure(kapi::devices::driver_match_errc::no_match);
@@ -52,9 +54,14 @@ namespace
{
using kapi::devices::bus::bus;
- [[nodiscard]] auto protocol() -> kapi::devices::bus_protocol * override
+ [[nodiscard]] auto query_facet(kapi::capabilities::facet_id id) -> void * override
{
- return &bus_protocol;
+ if (id == test_protocol::id || id == kapi::devices::bus_protocol::id)
+ {
+ return &bus_protocol;
+ }
+
+ return kapi::devices::bus::query_facet(id);
}
unsigned match_calls{};
@@ -106,14 +113,14 @@ namespace
mutable unsigned probe_calls;
protected:
- auto query_interface(kapi::devices::interface_id interface) -> void * override
+ auto query_facet(kapi::capabilities::facet_id facet) -> void * override
{
- if (interface == test_identification::id)
+ if (facet == test_identification::id)
{
return static_cast<test_identification *>(this);
}
- return kapi::devices::driver::query_interface(interface);
+ return kapi::devices::driver::query_facet(facet);
}
private:
diff --git a/kernel/kapi/devices/facet_registry.cpp b/kernel/kapi/devices/facet_registry.cpp
new file mode 100644
index 00000000..4aeebfc1
--- /dev/null
+++ b/kernel/kapi/devices/facet_registry.cpp
@@ -0,0 +1,216 @@
+#include <kapi/devices/facet_registry.hpp>
+
+#include <kapi/devices.hpp>
+#include <kapi/system.hpp>
+#include <kapi/test_support/devices.hpp>
+
+#include <kstd/memory.hpp>
+#include <kstd/result.hpp>
+#include <kstd/string.hpp>
+#include <kstd/system_error.hpp>
+#include <kstd/vector.hpp>
+
+#include <algorithm>
+#include <optional>
+#include <string_view>
+#include <utility>
+
+namespace kapi::devices
+{
+
+ namespace
+ {
+ constinit auto static registry = std::optional<facet_registry>{};
+ }
+
+ auto facet_registry::init() -> void
+ {
+ if (registry.has_value())
+ {
+ system::panic("[kernel] Device facet registry has already been initialized.");
+ }
+
+ registry.emplace();
+ }
+
+ auto facet_registry::get() -> facet_registry &
+ {
+ if (!registry)
+ {
+ system::panic("[kernel] Device facet registry has not been initialized.");
+ }
+
+ return *registry;
+ }
+
+ auto facet_registry::do_publish(kstd::shared_ptr<device> device, kstd::string name, kapi::capabilities::facet_id id,
+ void * facet) -> kstd::result<void>
+ {
+ // TODO: lock registry
+
+ erase_if(m_entries, [id](auto e) { return e.id() == id && !e.device(); });
+
+ if (!device || !facet || name.empty())
+ {
+ return kstd::failure(make_error_code(kstd::errc::invalid_argument));
+ }
+
+ auto already_published = std::ranges::any_of(
+ m_entries, [&](auto const & entry) { return entry.id() == id && entry.device().get() == device.get(); });
+
+ if (already_published)
+ {
+ return kstd::failure(make_error_code(kstd::errc::file_exists));
+ }
+
+ auto & published = m_entries.emplace_back(device, std::move(name), id, facet);
+
+ do_notify_published(id, published);
+
+ return kstd::success();
+ }
+
+ auto facet_registry::do_notify_published(kapi::capabilities::facet_id id, entry const & published) -> void
+ {
+ std::ranges::for_each(m_observers, [&](auto observer) {
+ if (auto locked_observer = observer.lock())
+ {
+ locked_observer->on_facet_published(id, published);
+ }
+ });
+
+ std::ranges::for_each(m_static_observers, [&](auto observer) { observer->on_facet_published(id, published); });
+ }
+
+ auto facet_registry::do_notify_withdrawn(kapi::capabilities::facet_id id, device const & device) -> void
+ {
+ std::ranges::for_each(m_observers, [&](auto observer) {
+ if (auto locked_observer = observer.lock())
+ {
+ locked_observer->on_facet_withdrawn(id, const_cast<devices::device &>(device));
+ }
+ });
+
+ std::ranges::for_each(m_static_observers, [&](auto observer) {
+ observer->on_facet_withdrawn(id, const_cast<devices::device &>(device));
+ });
+ }
+
+ auto facet_registry::withdraw(device const & device, kapi::capabilities::facet_id id) -> void
+ {
+ // TODO: lock registry
+
+ auto did_remove = erase_if(m_entries, [&](auto e) {
+ auto locked_device = e.device();
+ return e.id() == id && locked_device && locked_device.get() == &device;
+ }) != 0;
+
+ if (did_remove)
+ {
+ do_notify_withdrawn(id, device);
+ }
+ }
+
+ auto facet_registry::withdraw_all_for(device const & device) -> void
+ {
+ // TODO: lock registry
+
+ auto withdrawn_facets = kstd::vector<kapi::capabilities::facet_id>{};
+
+ erase_if(m_entries, [&](auto e) {
+ auto locked_device = e.device();
+ auto do_erase = locked_device && locked_device.get() == &device;
+ if (do_erase)
+ {
+ withdrawn_facets.push_back(e.id());
+ }
+ return do_erase;
+ });
+
+ std::ranges::for_each(withdrawn_facets, [&](auto facet) { do_notify_withdrawn(facet, device); });
+ }
+
+ auto facet_registry::all(kapi::capabilities::facet_id id) const -> kstd::vector<entry>
+ {
+ // TODO: lock registry
+
+ auto filtered = m_entries;
+ erase_if(filtered, [&](auto e) {
+ auto locked_device = e.device();
+ return !(e.id() == id && locked_device);
+ });
+ return filtered;
+ }
+
+ auto facet_registry::resolve(kapi::capabilities::facet_id id, 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())
+ {
+ return nullptr;
+ }
+ else if (auto device = found->device())
+ {
+ return resolve(id, *device);
+ }
+
+ return nullptr;
+ }
+
+ auto facet_registry::resolve(kapi::capabilities::facet_id id, device & device) -> void *
+ {
+ // TODO: lock registry
+
+ if (auto by_device = device.facet(id))
+ {
+ return by_device;
+ }
+
+ auto found = std::ranges::find_if(m_entries, [&](auto e) {
+ auto locked_device = e.device();
+ return e.id() == id && locked_device && locked_device.get() == &device;
+ });
+
+ if (found == m_entries.cend())
+ {
+ return nullptr;
+ }
+
+ return found->untyped_facet();
+ }
+
+ auto facet_registry::subscribe(kstd::weak_ptr<facet_registry_observer> observer) -> void
+ {
+ // TODO: lock registry
+
+ erase_if(m_observers, [](auto const & observer) { return observer.expired(); });
+ m_observers.push_back(observer);
+ }
+
+ auto facet_registry::subscribe(facet_registry_observer & observer) -> void
+ {
+ // TODO: lock registry
+
+ m_static_observers.push_back(&observer);
+ }
+
+ auto facet_registry::unsubscribe(facet_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
+{
+ auto deinit_facet_registry() -> void
+ {
+ kapi::devices::registry.reset();
+ }
+} // namespace kapi::test_support::devices
diff --git a/kernel/kapi/devices/interface_registry.tests.cpp b/kernel/kapi/devices/facet_registry.tests.cpp
index 071b9a6d..4ad3f763 100644
--- a/kernel/kapi/devices/interface_registry.tests.cpp
+++ b/kernel/kapi/devices/facet_registry.tests.cpp
@@ -10,7 +10,7 @@ namespace
{
struct probe_device
{
- constexpr auto static id = kapi::devices::interface_id{"probe"};
+ constexpr auto static id = kapi::capabilities::facet_id{"probe"};
virtual ~probe_device() = default;
@@ -19,7 +19,7 @@ namespace
struct const_device
{
- constexpr auto static id = kapi::devices::interface_id{"flip"};
+ constexpr auto static id = kapi::capabilities::facet_id{"flip"};
virtual ~const_device() = default;
@@ -31,7 +31,7 @@ namespace
struct unimplemented_device
{
- constexpr auto static id = kapi::devices::interface_id{"unimplemented"};
+ constexpr auto static id = kapi::capabilities::facet_id{"unimplemented"};
virtual ~unimplemented_device() = default;
};
@@ -49,18 +49,18 @@ namespace
return m_value;
}
- auto query_interface(kapi::devices::interface_id interface) -> void * override
+ auto query_facet(kapi::capabilities::facet_id facet) -> void * override
{
- if (interface == probe_device::id)
+ if (facet == probe_device::id)
{
return static_cast<probe_device *>(this);
}
- if (interface == const_device::id)
+ if (facet == const_device::id)
{
return m_const_device;
}
- return kapi::devices::device::query_interface(interface);
+ return kapi::devices::device::query_facet(facet);
}
private:
@@ -68,15 +68,14 @@ namespace
const_device * m_const_device;
};
- struct counting_observer final : kapi::devices::interface_registry_observer
+ struct counting_observer final : kapi::devices::facet_registry_observer
{
- auto on_interface_published(kapi::devices::interface_id, kapi::devices::interface_registry::entry const &)
- -> void override
+ auto on_facet_published(kapi::capabilities::facet_id, kapi::devices::facet_registry::entry const &) -> void override
{
++published;
}
- auto on_interface_withdrawn(kapi::devices::interface_id, kapi::devices::device &) -> void override
+ auto on_facet_withdrawn(kapi::capabilities::facet_id, kapi::devices::device &) -> void override
{
++withdrawn;
}
@@ -85,19 +84,18 @@ namespace
std::size_t withdrawn{};
};
- struct evil_observer final : kapi::devices::interface_registry_observer
+ struct evil_observer final : kapi::devices::facet_registry_observer
{
explicit evil_observer(kstd::shared_ptr<counting_observer> & victim)
: m_victim{victim}
{}
- auto on_interface_published(kapi::devices::interface_id, kapi::devices::interface_registry::entry const &)
- -> void override
+ auto on_facet_published(kapi::capabilities::facet_id, kapi::devices::facet_registry::entry const &) -> void override
{
m_victim.reset();
}
- auto on_interface_withdrawn(kapi::devices::interface_id, kapi::devices::device &) -> void override
+ auto on_facet_withdrawn(kapi::capabilities::facet_id, kapi::devices::device &) -> void override
{
m_victim.reset();
}
@@ -108,46 +106,46 @@ namespace
} // namespace
-SCENARIO("Publishing and finding a device", "[kapi][devices][interface_registry]")
+SCENARIO("Publishing and finding a device", "[kapi][devices][facet_registry]")
{
- GIVEN("An empty registry, a device, and an interface the device implements by inheritance")
+ GIVEN("An empty registry, a device, and a facet the device implements by inheritance")
{
- auto registry = kapi::devices::interface_registry{};
- auto free_standing_interface = const_device{};
- auto device = kstd::make_shared<test_device>(128, free_standing_interface);
+ auto registry = kapi::devices::facet_registry{};
+ auto free_standing_facet = const_device{};
+ auto device = kstd::make_shared<test_device>(128, free_standing_facet);
- THEN("Publishing an interface without a name fails")
+ THEN("Publishing an facet without a name fails")
{
REQUIRE_FALSE(registry.publish<probe_device>(device, ""));
}
- WHEN("publishing the interface for the device")
+ WHEN("publishing the facet for the device")
{
- CHECK(device->is_a<probe_device>());
- CHECK(device->is_a<const_device>());
- auto published = registry.publish(device, "probe0", device->as<probe_device>());
+ CHECK(device->has_facet<probe_device>());
+ CHECK(device->has_facet<const_device>());
+ auto published = registry.publish(device, "probe0", device->facet<probe_device>());
THEN("publishing is successful")
{
REQUIRE(published);
}
- THEN("publishing the same device and interface with a different name fails")
+ THEN("publishing the same device and facet with a different name fails")
{
- REQUIRE_FALSE(registry.publish(device, "probe1", device->as<probe_device>()));
+ REQUIRE_FALSE(registry.publish(device, "probe1", device->facet<probe_device>()));
}
- THEN("publishing a second interface for the same device succeeds")
+ THEN("publishing a second facet for the same device succeeds")
{
REQUIRE(registry.publish<const_device>(device, "probe0"));
}
- THEN("publishing a free standing second interface for the same device succeeds")
+ THEN("publishing a free standing second facet for the same device succeeds")
{
- REQUIRE(registry.publish(device, "probe0", &free_standing_interface));
+ REQUIRE(registry.publish(device, "probe0", &free_standing_facet));
}
- AND_WHEN("getting all devices implementing that interface")
+ AND_WHEN("getting all devices implementing that facet")
{
auto probeable_devices = registry.all(probe_device::id);
@@ -168,12 +166,12 @@ SCENARIO("Publishing and finding a device", "[kapi][devices][interface_registry]
THEN("the returned implementation equals the result of device::as")
{
- REQUIRE(probeable_devices[0].implementation() == device->as<probe_device>());
+ REQUIRE(probeable_devices[0].untyped_facet() == device->facet<probe_device>());
}
- THEN("the interface provided function can be invoked")
+ THEN("the facet provided function can be invoked")
{
- auto implementation = probeable_devices[0].as<probe_device>();
+ auto implementation = probeable_devices[0].facet<probe_device>();
REQUIRE(implementation->get_value() == device->get_value());
}
}
@@ -198,7 +196,7 @@ SCENARIO("Publishing and finding a device", "[kapi][devices][interface_registry]
REQUIRE_FALSE(registry.resolve<probe_device>("probe1"));
}
- THEN("withdrawing an interface for a device removes it from the registry")
+ THEN("withdrawing an facet for a device removes it from the registry")
{
registry.withdraw(*device, probe_device::id);
REQUIRE_FALSE(registry.resolve<probe_device>("probe0"));
@@ -207,7 +205,7 @@ SCENARIO("Publishing and finding a device", "[kapi][devices][interface_registry]
WHEN("the device is destroyed without withdrawing it")
{
- CHECK(registry.publish(device, "probe0", device->as<probe_device>()));
+ CHECK(registry.publish(device, "probe0", device->facet<probe_device>()));
device.reset();
THEN("querying all does no longer report it")
@@ -224,7 +222,7 @@ SCENARIO("Publishing and finding a device", "[kapi][devices][interface_registry]
GIVEN("no device has ever been published")
{
- auto registry = kapi::devices::interface_registry{};
+ auto registry = kapi::devices::facet_registry{};
THEN("all() returns an empty vector")
{
@@ -234,31 +232,31 @@ SCENARIO("Publishing and finding a device", "[kapi][devices][interface_registry]
GIVEN("a null device")
{
- auto registry = kapi::devices::interface_registry{};
+ auto registry = kapi::devices::facet_registry{};
auto device = kstd::shared_ptr<kapi::devices::device>{};
- auto interface = const_device{};
+ auto facet = const_device{};
- THEN("publishing the interface for the device fails")
+ THEN("publishing the facet for the device fails")
{
- REQUIRE_FALSE(registry.publish(device, "probe0", &interface));
+ REQUIRE_FALSE(registry.publish(device, "probe0", &facet));
}
}
}
-SCENARIO("Interface registry notifies subscribers", "[kapi][devices][interface_registry]")
+SCENARIO("facet registry notifies subscribers", "[kapi][devices][facet_registry]")
{
GIVEN("a device and a subscribed observer")
{
- auto registry = kapi::devices::interface_registry{};
- auto free_standing_interface = const_device{};
- auto device = kstd::make_shared<test_device>(128, free_standing_interface);
+ auto registry = kapi::devices::facet_registry{};
+ auto free_standing_facet = const_device{};
+ auto device = kstd::make_shared<test_device>(128, free_standing_facet);
auto observer = kstd::make_shared<counting_observer>();
registry.subscribe(observer);
- WHEN("an interface is published for the device")
+ WHEN("an facet is published for the device")
{
- CHECK(registry.publish(device, "probe0", device->as<probe_device>()));
+ CHECK(registry.publish(device, "probe0", device->facet<probe_device>()));
THEN("the observer is notified exactly once")
{
@@ -267,9 +265,9 @@ SCENARIO("Interface registry notifies subscribers", "[kapi][devices][interface_r
}
}
- WHEN("an interface is published and then withdrawn")
+ WHEN("an facet is published and then withdrawn")
{
- CHECK(registry.publish(device, "probe0", device->as<probe_device>()));
+ CHECK(registry.publish(device, "probe0", device->facet<probe_device>()));
registry.withdraw(*device, probe_device::id);
THEN("the observer is notified of both exactly one")
@@ -285,7 +283,7 @@ SCENARIO("Interface registry notifies subscribers", "[kapi][devices][interface_r
THEN("publishing afterward does not crash")
{
- REQUIRE_NOTHROW(registry.publish(device, "probe0", device->as<probe_device>()));
+ REQUIRE_NOTHROW(registry.publish(device, "probe0", device->facet<probe_device>()));
}
}
@@ -295,12 +293,12 @@ SCENARIO("Interface registry notifies subscribers", "[kapi][devices][interface_r
THEN("publishing afterward does not crash")
{
- REQUIRE_NOTHROW(registry.publish(device, "probe0", device->as<probe_device>()));
+ REQUIRE_NOTHROW(registry.publish(device, "probe0", device->facet<probe_device>()));
}
THEN("the subscriber is not notified")
{
- REQUIRE_NOTHROW(registry.publish(device, "probe0", device->as<probe_device>()));
+ REQUIRE_NOTHROW(registry.publish(device, "probe0", device->facet<probe_device>()));
REQUIRE_NOTHROW(registry.withdraw(*device, probe_device::id));
REQUIRE(observer->published == 0);
REQUIRE(observer->withdrawn == 0);
@@ -310,9 +308,9 @@ SCENARIO("Interface registry notifies subscribers", "[kapi][devices][interface_r
GIVEN("two subscriber, the first destroying the second")
{
- auto registry = kapi::devices::interface_registry{};
- auto free_standing_interface = const_device{};
- auto device = kstd::make_shared<test_device>(128, free_standing_interface);
+ auto registry = kapi::devices::facet_registry{};
+ auto free_standing_facet = const_device{};
+ auto device = kstd::make_shared<test_device>(128, free_standing_facet);
auto second = kstd::make_shared<counting_observer>();
auto first = kstd::make_shared<evil_observer>(second);
@@ -320,9 +318,9 @@ SCENARIO("Interface registry notifies subscribers", "[kapi][devices][interface_r
registry.subscribe(first);
registry.subscribe(second);
- THEN("publishing an interface does not crash")
+ THEN("publishing an facet does not crash")
{
- REQUIRE_NOTHROW(registry.publish(device, "probe0", device->as<probe_device>()));
+ REQUIRE_NOTHROW(registry.publish(device, "probe0", device->facet<probe_device>()));
REQUIRE(second == nullptr);
}
}
diff --git a/kernel/kapi/devices/interface_registry.cpp b/kernel/kapi/devices/interface_registry.cpp
deleted file mode 100644
index 1d456b30..00000000
--- a/kernel/kapi/devices/interface_registry.cpp
+++ /dev/null
@@ -1,218 +0,0 @@
-#include <kapi/devices/interface_registry.hpp>
-
-#include <kapi/devices.hpp>
-#include <kapi/system.hpp>
-#include <kapi/test_support/devices.hpp>
-
-#include <kstd/memory.hpp>
-#include <kstd/result.hpp>
-#include <kstd/string.hpp>
-#include <kstd/system_error.hpp>
-#include <kstd/vector.hpp>
-
-#include <algorithm>
-#include <optional>
-#include <string_view>
-#include <utility>
-
-namespace kapi::devices
-{
-
- namespace
- {
- constinit auto static registry = std::optional<interface_registry>{};
- }
-
- auto interface_registry::init() -> void
- {
- if (registry.has_value())
- {
- system::panic("[kernel] Device interface registry has already been initialized.");
- }
-
- registry.emplace();
- }
-
- auto interface_registry::get() -> interface_registry &
- {
- if (!registry)
- {
- system::panic("[kernel] Device interface registry has not been initialized.");
- }
-
- return *registry;
- }
-
- 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())
- {
- return kstd::failure(make_error_code(kstd::errc::invalid_argument));
- }
-
- auto already_published = std::ranges::any_of(m_entries, [&](auto const & entry) {
- return entry.interface() == interface && entry.device().get() == device.get();
- });
-
- if (already_published)
- {
- return kstd::failure(make_error_code(kstd::errc::file_exists));
- }
-
- auto & published = m_entries.emplace_back(device, std::move(name), interface, implementation);
-
- do_notify_published(interface, published);
-
- return kstd::success();
- }
-
- 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();
- 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();
- return !(e.interface() == interface && locked_device);
- });
- return filtered;
- }
-
- 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())
- {
- return nullptr;
- }
- else if (auto device = found->device())
- {
- return resolve(interface, *device);
- }
-
- return nullptr;
- }
-
- auto interface_registry::resolve(interface_id interface, device & device) -> void *
- {
- // TODO: lock registry
-
- if (auto by_device = device.as(interface))
- {
- return by_device;
- }
-
- auto found = std::ranges::find_if(m_entries, [&](auto e) {
- auto locked_device = e.device();
- return e.interface() == interface && locked_device && locked_device.get() == &device;
- });
-
- if (found == m_entries.cend())
- {
- return nullptr;
- }
-
- 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
-{
- auto deinit_interface_registry() -> void
- {
- kapi::devices::registry.reset();
- }
-} // namespace kapi::test_support::devices