2

As described in D-Bus documentation, all IPC calls considered as asynchronous. When Qt calls remote D-Bus object through QDBusAbstractInterface, there's QBusPendingCall<T> which is fully async and provide signalling when call ran to completion.

In my application design I want to implement async call on my object adaptor, but current Qt/DBus implementation assumes, that all method calls are blocking.

So, there's a question: is there proper way to implement handling D-Bus method call asynchronously?

Sharihin
  • 140
  • 11
  • This question would be more likely to get an answer, if you showed example of one actual blocking method. Now it is a bit unclear at least to me (then again I haven't used dbus, really). – hyde Aug 11 '16 at 19:07

1 Answers1

0

This is explained pretty well in Declaring Slots in D-Bus Adaptors.

We do this by writing a slot that stores the request data in a persistent structure, indicating to the caller using QDBusMessage::setDelayedReply(true) that the response will be sent later.

struct RequestData
{
    QString request;
    QString processedData;
    QDBusMessage reply;
};

QString processRequest(const QString &request, const QDBusMessage &message)
{
    RequestData *data = new RequestData;
    data->request = request;
    message.setDelayedReply(true);
    data->reply = message.createReply();
    QDBusConnection::sessionBus().send(data->reply);

    appendRequest(data);
    return QString();
}

The use of QDBusConnection::sessionBus().send(data->reply) is needed to explicitly inform the caller that the response will be delayed. In this case, the return value is unimportant; we return an arbitrary value to satisfy the compiler.

When the request is processed and a reply is available, it should be sent using the QDBusMessage object that was obtained. In our example, the reply code could be something as follows:

void sendReply(RequestData *data)
{
    // data->processedData has been initialized with the request's reply
    QDBusMessage &reply = &data->reply;

    // send the reply over D-Bus:
    reply << data->processedData;
    QDBusConnection::sessionBus().send(reply);

    // dispose of the transaction data
    delete data;
}

As can be seen in the example, when a delayed reply is in place, the return value(s) from the slot will be ignored by Qt D-Bus. They are used only to determine the slot's signature when communicating the adaptor's description to remote applications, or in case the code in the slot decides not to use a delayed reply.

The delayed reply itself is requested from Qt D-Bus by calling QDBusMessage::reply() on the original message. It then becomes the responsibility of the called code to eventually send a reply to the caller.

Warning: When a caller places a method call and waits for a reply, it will only wait for a limited amount of time. Slots intending to take a long time to complete should make that fact clear in documentation so that callers properly set higher timeouts.

Toby Speight
  • 27,591
  • 48
  • 66
  • 103
pn1029
  • 16
  • 1
  • 2
  • 1
    Whilst this may theoretically answer the question, [it would be preferable](//meta.stackexchange.com/q/8259) to include the essential parts of the answer here, and provide the link for reference. – Adrian Mole Feb 25 '20 at 13:00