forked from Kistler-Group/sdbus-cpp
Introduce support for asynchronous D-Bus method calls on the client side (#42)
Fixes #32
This commit is contained in:
@@ -648,6 +648,17 @@ MethodReply MethodCall::createErrorReply(const Error& error) const
|
||||
return MethodReply(sdbusErrorReply);
|
||||
}
|
||||
|
||||
AsyncMethodCall::AsyncMethodCall(MethodCall&& call) noexcept
|
||||
: Message(call)
|
||||
{
|
||||
}
|
||||
|
||||
void AsyncMethodCall::send(void* callback, void* userData) const
|
||||
{
|
||||
auto r = sd_bus_call_async(nullptr, nullptr, (sd_bus_message*)getMsg(), (sd_bus_message_handler_t)callback, userData, 0);
|
||||
SDBUS_THROW_ERROR_IF(r < 0, "Failed to call method asynchronously", -r);
|
||||
}
|
||||
|
||||
void MethodReply::send() const
|
||||
{
|
||||
auto r = sd_bus_send(nullptr, (sd_bus_message*)getMsg(), nullptr);
|
||||
|
||||
@@ -66,11 +66,22 @@ MethodCall ObjectProxy::createMethodCall(const std::string& interfaceName, const
|
||||
return connection_->createMethodCall(destination_, objectPath_, interfaceName, methodName);
|
||||
}
|
||||
|
||||
AsyncMethodCall ObjectProxy::createAsyncMethodCall(const std::string& interfaceName, const std::string& methodName)
|
||||
{
|
||||
return AsyncMethodCall{createMethodCall(interfaceName, methodName)};
|
||||
}
|
||||
|
||||
MethodReply ObjectProxy::callMethod(const MethodCall& message)
|
||||
{
|
||||
return message.send();
|
||||
}
|
||||
|
||||
void ObjectProxy::callMethod(const AsyncMethodCall& message, async_reply_handler asyncReplyCallback)
|
||||
{
|
||||
// The new-ed handler gets deleted in the sdbus_async_reply_handler
|
||||
message.send((void*)&ObjectProxy::sdbus_async_reply_handler, new async_reply_handler(std::move(asyncReplyCallback)));
|
||||
}
|
||||
|
||||
void ObjectProxy::registerSignalHandler( const std::string& interfaceName
|
||||
, const std::string& signalName
|
||||
, signal_handler signalHandler )
|
||||
@@ -136,11 +147,31 @@ void ObjectProxy::registerSignalHandlers(sdbus::internal::IConnection& connectio
|
||||
}
|
||||
}
|
||||
|
||||
int ObjectProxy::sdbus_async_reply_handler(sd_bus_message *sdbusMessage, void *userData, sd_bus_error *retError)
|
||||
{
|
||||
MethodReply message(sdbusMessage);
|
||||
|
||||
// We are assuming the ownership of the async reply handler pointer passed here
|
||||
std::unique_ptr<async_reply_handler> asyncReplyCallback{static_cast<async_reply_handler*>(userData)};
|
||||
assert(asyncReplyCallback != nullptr);
|
||||
|
||||
if (!sd_bus_error_is_set(retError))
|
||||
{
|
||||
(*asyncReplyCallback)(message, nullptr);
|
||||
}
|
||||
else
|
||||
{
|
||||
sdbus::Error error(retError->name, retError->message);
|
||||
(*asyncReplyCallback)(message, &error);
|
||||
}
|
||||
}
|
||||
|
||||
int ObjectProxy::sdbus_signal_callback(sd_bus_message *sdbusMessage, void *userData, sd_bus_error */*retError*/)
|
||||
{
|
||||
Signal message(sdbusMessage);
|
||||
|
||||
auto* object = static_cast<ObjectProxy*>(userData);
|
||||
assert(object != nullptr);
|
||||
// Note: The lookup can be optimized by using sorted vectors instead of associative containers
|
||||
auto& callback = object->interfaces_[message.getInterfaceName()].signals_[message.getMemberName()].callback_;
|
||||
assert(callback);
|
||||
|
||||
@@ -53,7 +53,9 @@ namespace internal {
|
||||
~ObjectProxy() override;
|
||||
|
||||
MethodCall createMethodCall(const std::string& interfaceName, const std::string& methodName) override;
|
||||
AsyncMethodCall createAsyncMethodCall(const std::string& interfaceName, const std::string& methodName) override;
|
||||
MethodReply callMethod(const MethodCall& message) override;
|
||||
void callMethod(const AsyncMethodCall& message, async_reply_handler asyncReplyCallback) override;
|
||||
|
||||
void registerSignalHandler( const std::string& interfaceName
|
||||
, const std::string& signalName
|
||||
@@ -63,6 +65,7 @@ namespace internal {
|
||||
private:
|
||||
bool listensToSignals() const;
|
||||
void registerSignalHandlers(sdbus::internal::IConnection& connection);
|
||||
static int sdbus_async_reply_handler(sd_bus_message *sdbusMessage, void *userData, sd_bus_error *retError);
|
||||
static int sdbus_signal_callback(sd_bus_message *sdbusMessage, void *userData, sd_bus_error *retError);
|
||||
|
||||
private:
|
||||
|
||||
Reference in New Issue
Block a user