-
Notifications
You must be signed in to change notification settings - Fork 20
Standardize facelift dbus communication #303
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from 8 commits
d451419
47b4a42
3c8f9ad
3d385a1
7fb1d9c
698e225
2cf600d
a3e6151
10557c3
3ed6fe9
92e7677
277b7e5
73c9a06
8e122fb
33b996d
8e2bd56
adcce61
b359770
1d94e76
1e5ab12
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -36,14 +36,10 @@ | |
| {% set className = interfaceName + proxyTypeNameSuffix %} | ||
|
|
||
| #include "{{className}}.h" | ||
|
|
||
| {{module.namespaceCppOpen}} | ||
|
|
||
| {{className}}::{{className}}(QObject *parent) : BaseType(parent) | ||
| {% for property in interface.properties %} | ||
| {% if property.type.is_interface %} | ||
| , m_{{property.name}}Proxy(*this) | ||
| {% endif %} | ||
| {% if property.type.is_model %} | ||
| , m_{{property.name}}(*this) | ||
| {% endif %} | ||
|
|
@@ -55,76 +51,132 @@ | |
| {% endif %} | ||
| } | ||
|
|
||
| void {{className}}::deserializePropertyValues(InputIPCMessage &msg, bool isCompleteSnapshot) | ||
| void {{className}}::unmarshalProperties(const QVariantMap& values) | ||
| { | ||
| {% for property in interface.properties %} | ||
| {% if property.type.is_interface %} | ||
| bool emit_{{property.name}}ChangeSignal = false; | ||
| QString {{property.name}}_objectPath; | ||
| if (deserializeOptionalValue(msg, {{property.name}}_objectPath, isCompleteSnapshot)) | ||
| { | ||
| m_{{property.name}}Proxy.update({{property.name}}_objectPath); | ||
| m_{{property.name}} = m_{{property.name}}Proxy.getValue(); | ||
| emit_{{property.name}}ChangeSignal = true; | ||
| QMap<QString, bool> emitChangeSignal; | ||
|
idleroamer marked this conversation as resolved.
Outdated
|
||
| for (const QString &propertyName: values.keys()) { | ||
| {% for property in interface.properties %} | ||
| if (propertyName == QStringLiteral("{{property.name}}")) { | ||
| {% if property.type.is_interface %} | ||
| const {{property.interfaceCppType}} previous_{{property.name}}_Value = m_{{property.name}}; | ||
| m_{{property.name}} = castFromQVariant<{{property.interfaceCppType}}>(values[propertyName]); | ||
| emitChangeSignal[QStringLiteral("{{property.name}}")] = ((previous_{{property.name}}_Value != m_{{property.name}})); | ||
| {% elif property.type.is_model %} | ||
| emitChangeSignal[QStringLiteral("{{property.name}}")] = true; | ||
| int {{property.name}}Size = castFromQVariant<int>(values[propertyName]); | ||
| m_{{property.name}}.beginResetModel(); | ||
| m_{{property.name}}.reset({{property.name}}Size, std::bind(&ThisType::{{property.name}}Data, this, std::placeholders::_1)); | ||
| m_{{property.name}}.endResetModel(); | ||
| {% else %} | ||
| const auto previous_{{property.name}}_Value = m_{{property.name}}; | ||
| m_{{property.name}} = castFromQVariant<{{property.interfaceCppType}}>(values[propertyName]); | ||
| emitChangeSignal[QStringLiteral("{{property.name}}")] = ((previous_{{property.name}}_Value != m_{{property.name}})); | ||
| {% endif %} | ||
| } | ||
|
idleroamer marked this conversation as resolved.
Outdated
|
||
| {% endfor %} | ||
| if (propertyName == QStringLiteral("ready")) { | ||
| bool previousIsReady = this->ready(); | ||
| m_serviceReady = castFromQVariant<bool>(values[propertyName]); | ||
| emitChangeSignal[QStringLiteral("ready")] = (previousIsReady != m_serviceReady); | ||
| } | ||
| } | ||
| {% elif property.type.is_model %} | ||
| bool emit_{{property.name}}ChangeSignal = false; | ||
| if (isCompleteSnapshot) { | ||
| int {{property.name}}Size; | ||
| deserializeValue(msg, {{property.name}}Size); | ||
| m_{{property.name}}.beginResetModel(); | ||
| m_{{property.name}}.reset({{property.name}}Size, std::bind(&ThisType::{{property.name}}Data, this, std::placeholders::_1)); | ||
| m_{{property.name}}.endResetModel(); | ||
| emit_{{property.name}}ChangeSignal = true; | ||
| for (const QString &propertyName: emitChangeSignal.keys()) { | ||
| {% for property in interface.properties %} | ||
| if (propertyName == QStringLiteral("{{property.name}}") && emitChangeSignal[propertyName]) { | ||
| emit {{property.name}}Changed(); | ||
| } | ||
| {% endfor %} | ||
| if (propertyName == QStringLiteral("ready") && emitChangeSignal[propertyName]) { | ||
| emit readyChanged(); | ||
| } | ||
| } | ||
| {% else %} | ||
| const auto previous_{{property.name}}_Value = m_{{property.name}}; | ||
| deserializeOptionalValue(msg, m_{{property.name}}, isCompleteSnapshot); | ||
| bool emit_{{property.name}}ChangeSignal = isCompleteSnapshot && ((previous_{{property.name}}_Value != m_{{property.name}})); | ||
| {% endif %} | ||
| {% endfor %} | ||
|
|
||
| bool emit_ReadyChangeSignal = deserializeReadyValue(msg, isCompleteSnapshot) && isCompleteSnapshot; | ||
|
|
||
| {% for property in interface.properties %} | ||
| if (emit_{{property.name}}ChangeSignal) | ||
| emit {{property.name}}Changed(); | ||
| {% endfor %} | ||
|
|
||
| if (emit_ReadyChangeSignal) | ||
| emit readyChanged(); | ||
|
|
||
| } | ||
|
|
||
| void {{className}}::deserializeSignal(InputIPCMessage &msg) | ||
| void {{className}}::handleSignals(InputIPCMessage& msg) | ||
| { | ||
| SignalID member; | ||
| deserializeValue(msg, member); | ||
|
|
||
| Q_UNUSED(msg) | ||
| {% for event in interface.signals %} | ||
| if (member == SignalID::{{event}}) | ||
| { | ||
| if (msg.member() == QStringLiteral("{{event}}")) { | ||
| QListIterator<QVariant> argumentsIterator(msg.arguments()); | ||
| {% for parameter in event.parameters %} | ||
| {{parameter.interfaceCppType}} param_{{parameter.name}}; | ||
| deserializeValue(msg, param_{{parameter.name}}); | ||
| param_{{parameter.name}} = (argumentsIterator.hasNext() ? castFromQVariant<{{parameter.interfaceCppType}}>(argumentsIterator.next()):{% if not parameter.type.is_interface %}{{parameter.interfaceCppType}}(){% else %}nullptr{% endif %}); | ||
| {% endfor %} | ||
| emit {{event}}( | ||
| {%- set comma = joiner(", ") -%} | ||
| {%- for parameter in event.parameters -%} | ||
| {{ comma() }}param_{{parameter.name}} | ||
| {%- endfor -%} ); | ||
| } else | ||
|
idleroamer marked this conversation as resolved.
|
||
| } | ||
| {% endfor %} | ||
|
|
||
| {% if interface.hasModelProperty %} | ||
| this->onModelUpdateEvent(msg); | ||
| {% endif %} | ||
| } | ||
|
|
||
| const QList<QString>& {{className}}::getSignals() const | ||
|
idleroamer marked this conversation as resolved.
|
||
| { | ||
| static QList<QString> allSignals{ | ||
| {% for event in interface.signals %} | ||
| "{{event}}", | ||
| {% endfor %} | ||
| {% if interface.hasModelProperty %} | ||
| facelift::IPCCommon::MODEL_DATA_CHANGED_MESSAGE_NAME, | ||
| facelift::IPCCommon::MODEL_INSERT_MESSAGE_NAME, | ||
| facelift::IPCCommon::MODEL_REMOVE_MESSAGE_NAME, | ||
| facelift::IPCCommon::MODEL_MOVE_MESSAGE_NAME, | ||
| facelift::IPCCommon::MODEL_RESET_MESSAGE_NAME, | ||
| {% endif %} | ||
| }; | ||
|
|
||
| return allSignals; | ||
| } | ||
|
|
||
| {% if interface.hasModelProperty %} | ||
| void {{className}}::onModelUpdateEvent(const InputIPCMessage& msg) | ||
| { | ||
| QListIterator<QVariant> argumentsIterator(msg.arguments()); | ||
| const QString& modelPropertyName = (argumentsIterator.hasNext() ? castFromQVariant<QString>(argumentsIterator.next()): QString()); | ||
| {% for property in interface.properties %} | ||
| if (member == SignalID::{{property.name}}) { | ||
| {% if property.type.is_model %} | ||
| if (modelPropertyName == QStringLiteral("{{property.name}}")) { | ||
| m_{{property.name}}.handleSignal(msg); | ||
| {% else %} | ||
| emit {{property.name}}Changed(); | ||
| } | ||
| {% endif %} | ||
| } else | ||
| {% endfor %} | ||
| BaseType::deserializeCommonSignal(static_cast<facelift::CommonSignalID>(member), this); | ||
| } | ||
| {% endif %} | ||
|
|
||
| void {{className}}::unmarshalPropertiesChanged(const QVariantMap& changedProperties) | ||
| { | ||
| {% if interface.properties %} | ||
| for (const QString &propertyName: changedProperties.keys()) { | ||
| {% for property in interface.properties %} | ||
| if (propertyName == QStringLiteral("{{property.name}}")) { | ||
| {% if property.type.is_model %} | ||
| int {{property.name}}Size = castFromQVariant<int>(changedProperties[propertyName]); | ||
| m_{{property.name}}.beginResetModel(); | ||
| m_{{property.name}}.reset({{property.name}}Size, std::bind(&ThisType::{{property.name}}Data, this, std::placeholders::_1)); | ||
| m_{{property.name}}.endResetModel(); | ||
| {% else %} | ||
| m_{{property.name}} = castFromQVariant<{{property.interfaceCppType}}>(changedProperties[propertyName]); | ||
| {% endif %} | ||
| } | ||
| {% endfor %} | ||
| } | ||
| for (const QString &propertyName: changedProperties.keys()) { | ||
| {% for property in interface.properties %} | ||
| if (propertyName == QStringLiteral("{{property.name}}")) { | ||
| {% if not property.type.is_model %} | ||
| emit {{property.name}}Changed(); | ||
| {% endif %} | ||
| } | ||
| {% endfor %} | ||
| } | ||
| {% else %} | ||
| Q_UNUSED(changedProperties); | ||
| {% endif %} | ||
| } | ||
|
|
||
| {% for property in interface.properties %} | ||
|
|
@@ -134,7 +186,7 @@ void {{className}}::deserializeSignal(InputIPCMessage &msg) | |
| void {{className}}::set{{property}}({{property.cppMethodArgumentType}} newValue) | ||
| { | ||
| {% if (not property.type.is_interface) %} | ||
| ipc()->sendSetterCall(memberID(MethodID::set{{property.name}}, "set{{property.name}}"), newValue); | ||
| ipc()->sendSetterCall("{{property.name}}", newValue); | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. FYI, the construct you broke here is meant to provide a way for that generated code to be usable with both an IPC transport channel where method IDs are strings (such as DBus), and an IPC where method IDs are integer (such as the the current "local" IPC, and the hi-performance IPC which I have been working on). Using integers instead of strings is obviously more efficient.
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can we please stop the "performance" discussion? now you are discussing about "future possible performance degrades with some not in-place high performance IPC!!!".
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The local IPC uses integer IDs, so we are not talking about the future.. The current approach should work with your changes.
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The performance claims needs to be backed up by actuall KPI measurement
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I have no doubt that sending an integer (which does not even need to be wider than 8 bits) is faster than sending a multi-character string. Also, string comparisons are not free, so the processing of an incoming request is also faster if an integer is used as method ID since no comparison is even needed.
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. A simple benchmark of signal 30 character long being emitted/received 10000 times shows followings: Current implementation Current PR: A signal name comparison is not a bottleneck.
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Do those figures tell us that using a string is faster than using an integer ?
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. No, those figures tell us whether we send MessageIDs as strings or as integers is not a performance bottleneck. I appreciate your time but I have the feeling you even haven't looked at the PR? the "sendSetterCall" is internal call between IPCProxy and Local/DBusIPCProxyBinder and using integers is simply superfluous You had performance claims now you are talking again about some IPC which is not even there yet AGAIN.
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. There is a misunderstanding here.
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. That is a fine suggestion. Though tomorrow is a little tight in the afternoon, so let me know if tomorrow morning or the Friday's afternoon fits your calendar, otherwise we postpone to next week. |
||
| {% else %} | ||
| Q_ASSERT(false); // Writable interface properties are unsupported | ||
| {% endif %} | ||
|
|
@@ -168,12 +220,11 @@ void {{className}}::{{operation.name}}( | |
| {%- endfor -%} ){% if operation.is_const %} const{% endif %} | ||
| { | ||
| {% if (operation.hasReturnValue) %} | ||
| {{operation.interfaceCppType}} returnValue; | ||
| ipc()->sendMethodCallWithReturn(memberID(MethodID::{{operation.name}}, "{{operation.name}}"), returnValue | ||
| QList<QVariant> args = ipc()->sendMethodCallWithReturn(memberID(MethodID::{{operation.name}}, "{{operation.name}}") | ||
| {%- for parameter in operation.parameters -%} | ||
| , {{parameter.name}} | ||
| {%- endfor -%} ); | ||
| return returnValue; | ||
| return (!args.isEmpty() ? castFromQVariant<{{operation.interfaceCppType}}>(args.first()):{% if not (operation.type.is_interface) %}{{operation.cppType}}(){% else %}nullptr{% endif %}); | ||
| {% else %} | ||
| ipc()->sendMethodCall(memberID(MethodID::{{operation.name}}, "{{operation.name}}") | ||
| {%- for parameter in operation.parameters -%} | ||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.