Use offset to avoid lookups
In systemd vtable entries, each of property and method callbacks have a
version of the callback that takes an "offset" parameter. This allows
passing a userdata pointer at an offset from the original userdata
pointer. This allows us to optimize, and not have a O(n) lookup on our
vectors, and allows us to directly dereference the correct callback,
without needing to mess around with trying to find the callback we're
looking for.
Change-Id: I8a490aedbe475f6eab6112bb696c589d597eb71b
Signed-off-by: Ed Tanous <edtanous@google.com>
diff --git a/include/sdbusplus/asio/object_server.hpp b/include/sdbusplus/asio/object_server.hpp
index 3484d9c..a56e5df 100644
--- a/include/sdbusplus/asio/object_server.hpp
+++ b/include/sdbusplus/asio/object_server.hpp
@@ -557,84 +557,69 @@
}
static int get_handler(sd_bus* /*bus*/, const char* /*path*/,
- const char* /*interface*/, const char* property,
+ const char* /*interface*/, const char* /*property*/,
sd_bus_message* reply, void* userdata,
sd_bus_error* error)
{
- dbus_interface* data = static_cast<dbus_interface*>(userdata);
- auto func = std::find_if(data->property_callbacks_.begin(),
- data->property_callbacks_.end(),
- [&property](const auto& element) {
- return element.name == property;
- });
+ property_callback** func = static_cast<property_callback**>(userdata);
auto mesg = message_t(reply);
- if (func != data->property_callbacks_.end())
+#ifdef __EXCEPTIONS
+ try
{
-#ifdef __EXCEPTIONS
- try
- {
#endif
- return func->on_get(mesg);
+ return (*func)->on_get(mesg);
#ifdef __EXCEPTIONS
- }
-
- catch (const sdbusplus::exception_t& e)
- {
- return sd_bus_error_set(error, e.name(), e.description());
- }
- catch (...)
- {
- // hit default error below
- }
-#endif
}
+
+ catch (const sdbusplus::exception_t& e)
+ {
+ return sd_bus_error_set(error, e.name(), e.description());
+ }
+ catch (...)
+ {
+ // hit default error below
+ }
+#endif
return sd_bus_error_set_const(error, SD_BUS_ERROR_INVALID_ARGS,
nullptr);
}
static int set_handler(sd_bus* /*bus*/, const char* /*path*/,
- const char* /*interface*/, const char* property,
+ const char* /*interface*/, const char* /*property*/,
sd_bus_message* value, void* userdata,
sd_bus_error* error)
{
- dbus_interface* data = static_cast<dbus_interface*>(userdata);
- auto func = std::find_if(data->property_callbacks_.begin(),
- data->property_callbacks_.end(),
- [property](const auto& element) {
- return element.name == property;
- });
- auto mesg = message_t(value);
- if (func != data->property_callbacks_.end())
- {
-#ifdef __EXCEPTIONS
- try
- {
-#endif
- SetPropertyReturnValue status = func->on_set_message(mesg);
- if ((status == SetPropertyReturnValue::valueUpdated) ||
- (status == SetPropertyReturnValue::sameValueUpdated))
- {
- if (status != SetPropertyReturnValue::sameValueUpdated)
- {
- data->signal_property(property);
- }
- // There shouldn't be any other callbacks that want to
- // handle the message so just return a positive integer.
- return 1;
- }
-#ifdef __EXCEPTIONS
- }
+ property_callback** func = static_cast<property_callback**>(userdata);
- catch (const sdbusplus::exception_t& e)
- {
- return sd_bus_error_set(error, e.name(), e.description());
- }
- catch (...)
- {
- // hit default error below
- }
+ auto mesg = message_t(value);
+#ifdef __EXCEPTIONS
+ try
+ {
#endif
+ SetPropertyReturnValue status = (*func)->on_set_message(mesg);
+ if ((status == SetPropertyReturnValue::valueUpdated) ||
+ (status == SetPropertyReturnValue::sameValueUpdated))
+ {
+ if (status != SetPropertyReturnValue::sameValueUpdated)
+ {
+ // data->signal_property(property);
+ }
+ // There shouldn't be any other callbacks that want to
+ // handle the message so just return a positive integer.
+ return 1;
+ }
+#ifdef __EXCEPTIONS
}
+
+ catch (const sdbusplus::exception_t& e)
+ {
+ return sd_bus_error_set(error, e.name(), e.description());
+ }
+ catch (...)
+ {
+ // hit default error below
+ }
+#endif
return sd_bus_error_set_const(error, SD_BUS_ERROR_INVALID_ARGS,
nullptr);
}
@@ -642,36 +627,29 @@
static int method_handler(sd_bus_message* m, void* userdata,
sd_bus_error* error)
{
- dbus_interface* data = static_cast<dbus_interface*>(userdata);
+ method_callback** func = static_cast<method_callback**>(userdata);
auto mesg = message_t(m);
- auto member = mesg.get_member();
- auto func = std::find_if(
- data->method_callbacks_.begin(), data->method_callbacks_.end(),
- [&member](const auto& element) { return element.name == member; });
- if (func != data->method_callbacks_.end())
+#ifdef __EXCEPTIONS
+ try
{
-#ifdef __EXCEPTIONS
- try
- {
#endif
- int status = func->call(mesg);
- if (status == 1)
- {
- return status;
- }
+ int status = (*func)->call(mesg);
+ if (status == 1)
+ {
+ return status;
+ }
#ifdef __EXCEPTIONS
- }
-
- catch (const sdbusplus::exception_t& e)
- {
- return sd_bus_error_set(error, e.name(), e.description());
- }
- catch (...)
- {
- // hit default error below
- }
-#endif
}
+
+ catch (const sdbusplus::exception_t& e)
+ {
+ return sd_bus_error_set(error, e.name(), e.description());
+ }
+ catch (...)
+ {
+ // hit default error below
+ }
+#endif
return sd_bus_error_set_const(error, SD_BUS_ERROR_INVALID_ARGS,
nullptr);
}
@@ -699,20 +677,28 @@
vtable_.reserve(2 + property_callbacks_.size() +
method_callbacks_.size() + signals_.size());
vtable_.emplace_back(vtable::start());
+ pointers.push_back(this);
+
property_callbacks_.shrink_to_fit();
- for (const auto& element : property_callbacks_)
+ for (auto& element : property_callbacks_)
{
- vtable_.emplace_back(
- vtable::property(element.name.c_str(), element.signature,
- get_handler, set_handler, element.flags));
+ pointers.push_back(&element);
+ size_t pointer_off = (pointers.size() - 1) * sizeof(void*);
+ vtable_.emplace_back(vtable::property_o(
+ element.name.c_str(), element.signature, get_handler,
+ set_handler, pointer_off, element.flags));
}
+
method_callbacks_.shrink_to_fit();
- for (const auto& element : method_callbacks_)
+ for (auto& element : method_callbacks_)
{
- vtable_.emplace_back(
- vtable::method(element.name.c_str(), element.arg_signature,
- element.return_signature, method_handler));
+ pointers.push_back(&element);
+ size_t pointer_off = (pointers.size() - 1) * sizeof(void*);
+ vtable_.emplace_back(vtable::method_o(
+ element.name.c_str(), element.arg_signature,
+ element.return_signature, method_handler, pointer_off));
}
+
signals_.shrink_to_fit();
for (const auto& element : signals_)
{
@@ -726,7 +712,7 @@
interface_.emplace(static_cast<sdbusplus::bus_t&>(*conn_),
path_.c_str(), name_.c_str(),
static_cast<const sd_bus_vtable*>(&vtable_[0]),
- this);
+ pointers.data());
conn_->emit_interfaces_added(path_.c_str(),
std::vector<std::string>{name_});
if (!skipPropertyChangedSignal)
@@ -773,6 +759,8 @@
std::vector<property_callback> property_callbacks_;
std::vector<method_callback> method_callbacks_;
+ std::vector<void*> pointers;
+
std::vector<sd_bus_vtable> vtable_;
std::optional<sdbusplus::server::interface_t> interface_;
};