Introduce support for asynchronous server-side methods (#12)

* Add preliminary changes for async server methods

* Refactor the Message concept and break it into distinctive types

* Continue working on async server methods (high-level API mainly)

* Continue developing support for async server

* Finishing async server methods

* Finishing async server methods (fixing tests & cleaning up)

* A little code cleaning

* Add unit tests for type traits of free functions

* Support for generating async server methods in stub headers

* Update ChangeLog for v0.3.0

* Update the tutorial with how to use async server-side methods

* Update the TOC in sdbus-c++ tutorial

* Update numbering in TOC

* Remove unnecessary code

* Final cleanups
This commit is contained in:
Stanislav Angelovič
2018-07-02 11:22:00 +02:00
committed by Lukáš Ďurfina
parent b041f76bfc
commit d8fd053714
33 changed files with 866 additions and 223 deletions
+62 -27
View File
@@ -42,13 +42,13 @@ Connection::Connection(Connection::BusType type)
finishHandshake(bus);
exitLoopFd_ = createProcessingExitDescriptor();
notificationFd_ = createLoopNotificationDescriptor();
}
Connection::~Connection()
{
leaveProcessingLoop();
closeProcessingExitDescriptor(exitLoopFd_);
closeLoopNotificationDescriptor(notificationFd_);
}
void Connection::requestName(const std::string& name)
@@ -67,13 +67,15 @@ void Connection::enterProcessingLoop()
{
while (true)
{
auto processed = processPendingRequest(bus_.get());
auto processed = processPendingRequest();
if (processed)
continue; // Process next one
auto success = waitForNextRequest(bus_.get(), exitLoopFd_);
auto success = waitForNextRequest();
if (!success)
break; // Exit processing loop
if (success.asyncMsgsToProcess)
processAsynchronousMessages();
}
}
@@ -112,10 +114,10 @@ void Connection::removeObjectVTable(void* vtableHandle)
sd_bus_slot_unref((sd_bus_slot *)vtableHandle);
}
sdbus::Message Connection::createMethodCall( const std::string& destination
, const std::string& objectPath
, const std::string& interfaceName
, const std::string& methodName ) const
sdbus::MethodCall Connection::createMethodCall( const std::string& destination
, const std::string& objectPath
, const std::string& interfaceName
, const std::string& methodName ) const
{
sd_bus_message *sdbusMsg{};
@@ -131,12 +133,12 @@ sdbus::Message Connection::createMethodCall( const std::string& destination
SDBUS_THROW_ERROR_IF(r < 0, "Failed to create method call", -r);
return Message(sdbusMsg, Message::Type::eMethodCall);
return MethodCall(sdbusMsg);
}
sdbus::Message Connection::createSignal( const std::string& objectPath
, const std::string& interfaceName
, const std::string& signalName ) const
sdbus::Signal Connection::createSignal( const std::string& objectPath
, const std::string& interfaceName
, const std::string& signalName ) const
{
sd_bus_message *sdbusSignal{};
@@ -151,7 +153,7 @@ sdbus::Message Connection::createSignal( const std::string& objectPath
SDBUS_THROW_ERROR_IF(r < 0, "Failed to create signal", -r);
return Message(sdbusSignal, Message::Type::eSignal);
return Signal(sdbusSignal);
}
void* Connection::registerSignalHandler( const std::string& objectPath
@@ -175,6 +177,13 @@ void Connection::unregisterSignalHandler(void* handlerCookie)
sd_bus_slot_unref((sd_bus_slot *)handlerCookie);
}
void Connection::sendReplyAsynchronously(const sdbus::MethodReply& reply)
{
std::lock_guard<std::mutex> guard(mutex_);
asyncReplies_.push(reply);
notifyProcessingLoop();
}
std::unique_ptr<sdbus::internal::IConnection> Connection::clone() const
{
return std::make_unique<sdbus::internal::Connection>(busType_);
@@ -211,10 +220,8 @@ void Connection::finishHandshake(sd_bus* bus)
SDBUS_THROW_ERROR_IF(r < 0, "Failed to flush bus on opening", -r);
}
int Connection::createProcessingExitDescriptor()
int Connection::createLoopNotificationDescriptor()
{
// Mechanism for graceful termination of processing loop
auto r = eventfd(0, EFD_SEMAPHORE | EFD_CLOEXEC);
SDBUS_THROW_ERROR_IF(r < 0, "Failed to create event object", -errno);
@@ -222,16 +229,23 @@ int Connection::createProcessingExitDescriptor()
return r;
}
void Connection::closeProcessingExitDescriptor(int fd)
void Connection::closeLoopNotificationDescriptor(int fd)
{
close(fd);
}
void Connection::notifyProcessingLoop()
{
assert(notificationFd_ >= 0);
uint64_t value = 1;
write(notificationFd_, &value, sizeof(value));
}
void Connection::notifyProcessingLoopToExit()
{
assert(exitLoopFd_ >= 0);
uint64_t value = 1;
write(exitLoopFd_, &value, sizeof(value));
exitLoopThread_ = true;
notifyProcessingLoop();
}
void Connection::joinWithProcessingLoop()
@@ -240,8 +254,10 @@ void Connection::joinWithProcessingLoop()
asyncLoopThread_.join();
}
bool Connection::processPendingRequest(sd_bus* bus)
bool Connection::processPendingRequest()
{
auto bus = bus_.get();
assert(bus != nullptr);
int r = sd_bus_process(bus, nullptr);
@@ -251,10 +267,23 @@ bool Connection::processPendingRequest(sd_bus* bus)
return r > 0;
}
bool Connection::waitForNextRequest(sd_bus* bus, int exitFd)
void Connection::processAsynchronousMessages()
{
std::lock_guard<std::mutex> guard(mutex_);
while (!asyncReplies_.empty())
{
auto reply = asyncReplies_.front();
asyncReplies_.pop();
reply.send();
}
}
Connection::WaitResult Connection::waitForNextRequest()
{
auto bus = bus_.get();
assert(bus != nullptr);
assert(exitFd != 0);
assert(notificationFd_ != 0);
auto r = sd_bus_get_fd(bus);
SDBUS_THROW_ERROR_IF(r < 0, "Failed to get bus descriptor", -r);
@@ -267,20 +296,26 @@ bool Connection::waitForNextRequest(sd_bus* bus, int exitFd)
uint64_t usec;
sd_bus_get_timeout(bus, &usec);
struct pollfd fds[] = {{sdbusFd, sdbusEvents, 0}, {exitFd, POLLIN, 0}};
struct pollfd fds[] = {{sdbusFd, sdbusEvents, 0}, {notificationFd_, POLLIN, 0}};
auto fdsCount = sizeof(fds)/sizeof(fds[0]);
r = poll(fds, fdsCount, usec == (uint64_t) -1 ? -1 : (usec+999)/1000);
if (r < 0 && errno == EINTR)
return true; // Try again
return {true, false}; // Try again
SDBUS_THROW_ERROR_IF(r < 0, "Failed to wait on the bus", -errno);
if (fds[1].revents & POLLIN)
return false; // Got exit notification
{
if (exitLoopThread_)
return {false, false}; // Got exit notification
return true;
// Otherwise we have some async messages to process
return {false, true};
}
return {true, false};
}
std::string Connection::composeSignalMatchFilter( const std::string& objectPath
+33 -15
View File
@@ -27,12 +27,14 @@
#define SDBUS_CXX_INTERNAL_CONNECTION_H_
#include <sdbus-c++/IConnection.h>
#include <sdbus-c++/Message.h>
#include "IConnection.h"
#include <systemd/sd-bus.h>
#include <memory>
#include <atomic>
#include <thread>
#include "IConnection.h"
#include <atomic>
#include <mutex>
#include <queue>
namespace sdbus { namespace internal {
@@ -62,13 +64,13 @@ namespace sdbus { namespace internal {
, void* userData ) override;
void removeObjectVTable(void* vtableHandle) override;
sdbus::Message createMethodCall( const std::string& destination
, const std::string& objectPath
, const std::string& interfaceName
, const std::string& methodName ) const override;
sdbus::Message createSignal( const std::string& objectPath
, const std::string& interfaceName
, const std::string& signalName ) const override;
sdbus::MethodCall createMethodCall( const std::string& destination
, const std::string& objectPath
, const std::string& interfaceName
, const std::string& methodName ) const override;
sdbus::Signal createSignal( const std::string& objectPath
, const std::string& interfaceName
, const std::string& signalName ) const override;
void* registerSignalHandler( const std::string& objectPath
, const std::string& interfaceName
@@ -77,25 +79,41 @@ namespace sdbus { namespace internal {
, void* userData ) override;
void unregisterSignalHandler(void* handlerCookie) override;
void sendReplyAsynchronously(const sdbus::MethodReply& reply) override;
std::unique_ptr<sdbus::internal::IConnection> clone() const override;
private:
struct WaitResult
{
bool msgsToProcess;
bool asyncMsgsToProcess;
operator bool()
{
return msgsToProcess || asyncMsgsToProcess;
}
};
static sd_bus* openBus(Connection::BusType type);
static void finishHandshake(sd_bus* bus);
static int createProcessingExitDescriptor();
static void closeProcessingExitDescriptor(int fd);
static bool processPendingRequest(sd_bus* bus);
static bool waitForNextRequest(sd_bus* bus, int exitFd);
static int createLoopNotificationDescriptor();
static void closeLoopNotificationDescriptor(int fd);
bool processPendingRequest();
void processAsynchronousMessages();
WaitResult waitForNextRequest();
static std::string composeSignalMatchFilter( const std::string& objectPath
, const std::string& interfaceName
, const std::string& signalName );
void notifyProcessingLoop();
void notifyProcessingLoopToExit();
void joinWithProcessingLoop();
private:
std::unique_ptr<sd_bus, decltype(&sd_bus_flush_close_unref)> bus_{nullptr, &sd_bus_flush_close_unref};
std::thread asyncLoopThread_;
std::atomic<int> exitLoopFd_{-1};
std::mutex mutex_;
std::queue<MethodReply> asyncReplies_;
std::atomic<bool> exitLoopThread_;
int notificationFd_{-1};
BusType busType_;
static constexpr const uint64_t POLL_TIMEOUT_USEC = 500000;
+12 -8
View File
@@ -32,7 +32,9 @@
// Forward declaration
namespace sdbus {
class Message;
class MethodCall;
class MethodReply;
class Signal;
}
namespace sdbus {
@@ -47,14 +49,14 @@ namespace internal {
, void* userData ) = 0;
virtual void removeObjectVTable(void* vtableHandle) = 0;
virtual sdbus::Message createMethodCall( const std::string& destination
, const std::string& objectPath
, const std::string& interfaceName
, const std::string& methodName ) const = 0;
virtual sdbus::MethodCall createMethodCall( const std::string& destination
, const std::string& objectPath
, const std::string& interfaceName
, const std::string& methodName ) const = 0;
virtual sdbus::Message createSignal( const std::string& objectPath
, const std::string& interfaceName
, const std::string& signalName ) const = 0;
virtual sdbus::Signal createSignal( const std::string& objectPath
, const std::string& interfaceName
, const std::string& signalName ) const = 0;
virtual void* registerSignalHandler( const std::string& objectPath
, const std::string& interfaceName
@@ -66,6 +68,8 @@ namespace internal {
virtual void enterProcessingLoopAsync() = 0;
virtual void leaveProcessingLoop() = 0;
virtual void sendReplyAsynchronously(const sdbus::MethodReply& reply) = 0;
virtual std::unique_ptr<sdbus::internal::IConnection> clone() const = 0;
virtual ~IConnection() = default;
+1
View File
@@ -5,6 +5,7 @@ libsdbus_c___la_SOURCES = \
Connection.cpp \
ConvenienceClasses.cpp \
Message.cpp \
MethodResult.cpp \
Object.cpp \
ObjectProxy.cpp \
Types.cpp \
+67 -63
View File
@@ -31,11 +31,10 @@
#include <systemd/sd-bus.h>
#include <cassert>
namespace sdbus { /*namespace internal {*/
namespace sdbus {
Message::Message(void *msg, Type type) noexcept
Message::Message(void *msg) noexcept
: msg_(msg)
, type_(type)
{
assert(msg_ != nullptr);
sd_bus_message_ref((sd_bus_message*)msg_);
@@ -52,7 +51,6 @@ Message& Message::operator=(const Message& other) noexcept
sd_bus_message_unref((sd_bus_message*)msg_);
msg_ = other.msg_;
type_ = other.type_;
ok_ = other.ok_;
sd_bus_message_ref((sd_bus_message*)msg_);
@@ -72,8 +70,6 @@ Message& Message::operator=(Message&& other) noexcept
msg_ = other.msg_;
other.msg_ = nullptr;
type_ = other.type_;
other.type_ = {};
ok_ = other.ok_;
other.ok_ = true;
@@ -540,59 +536,6 @@ void Message::rewind(bool complete)
SDBUS_THROW_ERROR_IF(r < 0, "Failed to rewind the message", -r);
}
Message Message::send() const
{
if (type_ == Type::eMethodCall)
{
sd_bus_message* sdbusReply{};
SCOPE_EXIT{ sd_bus_message_unref(sdbusReply); }; // Returned message will become an owner of sdbusReply
sd_bus_error sdbusError = SD_BUS_ERROR_NULL;
SCOPE_EXIT{ sd_bus_error_free(&sdbusError); };
auto r = sd_bus_call(nullptr, (sd_bus_message*)msg_, 0, &sdbusError, &sdbusReply);
if (sd_bus_error_is_set(&sdbusError))
{
throw sdbus::Error(sdbusError.name, sdbusError.message);
}
SDBUS_THROW_ERROR_IF(r < 0, "Failed to call method", -r);
return Message(sdbusReply);
}
else if (type_ == Type::eMethodReply)
{
auto r = sd_bus_send(nullptr, (sd_bus_message*)msg_, nullptr);
SDBUS_THROW_ERROR_IF(r < 0, "Failed to send reply", -r);
return Message();
}
else if (type_ == Type::eSignal)
{
auto r = sd_bus_send(nullptr, (sd_bus_message*)msg_, nullptr);
SDBUS_THROW_ERROR_IF(r < 0, "Failed to emit signal", -r);
return Message();
}
else
{
assert(false);
return Message();
}
}
Message Message::createReply() const
{
sd_bus_message *sdbusReply{};
SCOPE_EXIT{ sd_bus_message_unref(sdbusReply); }; // Returned message will become an owner of sdbusReply
auto r = sd_bus_message_new_method_return((sd_bus_message*)msg_, &sdbusReply);
SDBUS_THROW_ERROR_IF(r < 0, "Failed to create method reply", -r);
assert(sdbusReply != nullptr);
return Message(sdbusReply, Type::eMethodReply);
}
std::string Message::getInterfaceName() const
{
return sd_bus_message_get_interface((sd_bus_message*)msg_);
@@ -623,9 +566,70 @@ bool Message::isEmpty() const
return sd_bus_message_is_empty((sd_bus_message*)msg_);
}
Message::Type Message::getType() const
void* Message::getMsg() const
{
return type_;
return msg_;
}
MethodReply MethodCall::send() const
{
sd_bus_message* sdbusReply{};
SCOPE_EXIT{ sd_bus_message_unref(sdbusReply); }; // Returned message will become an owner of sdbusReply
sd_bus_error sdbusError = SD_BUS_ERROR_NULL;
SCOPE_EXIT{ sd_bus_error_free(&sdbusError); };
auto r = sd_bus_call(nullptr, (sd_bus_message*)getMsg(), 0, &sdbusError, &sdbusReply);
if (sd_bus_error_is_set(&sdbusError))
{
throw sdbus::Error(sdbusError.name, sdbusError.message);
}
SDBUS_THROW_ERROR_IF(r < 0, "Failed to call method", -r);
return MethodReply(sdbusReply);
}
MethodReply MethodCall::createReply() const
{
sd_bus_message *sdbusReply{};
SCOPE_EXIT{ sd_bus_message_unref(sdbusReply); }; // Returned message will become an owner of sdbusReply
auto r = sd_bus_message_new_method_return((sd_bus_message*)getMsg(), &sdbusReply);
SDBUS_THROW_ERROR_IF(r < 0, "Failed to create method reply", -r);
assert(sdbusReply != nullptr);
return MethodReply(sdbusReply);
}
MethodReply MethodCall::createErrorReply(const Error& error) const
{
sd_bus_error sdbusError = SD_BUS_ERROR_NULL;
SCOPE_EXIT{ sd_bus_error_free(&sdbusError); };
sd_bus_error_set(&sdbusError, error.getName().c_str(), error.getMessage().c_str());
sd_bus_message *sdbusErrorReply{};
SCOPE_EXIT{ sd_bus_message_unref(sdbusErrorReply); }; // Returned message will become an owner of sdbusErrorReply
auto r = sd_bus_message_new_method_error((sd_bus_message*)getMsg(), &sdbusErrorReply, &sdbusError);
SDBUS_THROW_ERROR_IF(r < 0, "Failed to create method error reply", -r);
assert(sdbusErrorReply != nullptr);
return MethodReply(sdbusErrorReply);
}
void MethodReply::send() const
{
auto r = sd_bus_send(nullptr, (sd_bus_message*)getMsg(), nullptr);
SDBUS_THROW_ERROR_IF(r < 0, "Failed to send reply", -r);
}
void Signal::send() const
{
auto r = sd_bus_send(nullptr, (sd_bus_message*)getMsg(), nullptr);
SDBUS_THROW_ERROR_IF(r < 0, "Failed to emit signal", -r);
}
Message createPlainMessage()
@@ -642,7 +646,7 @@ Message createPlainMessage()
r = sd_bus_message_new(bus, &sdbusMsg, _SD_BUS_MESSAGE_TYPE_INVALID);
SDBUS_THROW_ERROR_IF(r < 0, "Failed to create a new message", -r);
return Message(sdbusMsg, Message::Type::ePlainMessage);
return Message(sdbusMsg);
}
/*}*/}
}
+43
View File
@@ -0,0 +1,43 @@
/**
* (C) 2017 KISTLER INSTRUMENTE AG, Winterthur, Switzerland
*
* @file Object.cpp
*
* Created on: Nov 8, 2016
* Project: sdbus-c++
* Description: High-level D-Bus IPC C++ library based on sd-bus
*
* This file is part of sdbus-c++.
*
* sdbus-c++ is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 2.1 of the License, or
* (at your option) any later version.
*
* sdbus-c++ is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with sdbus-c++. If not, see <http://www.gnu.org/licenses/>.
*/
#include <sdbus-c++/MethodResult.h>
#include "Object.h"
namespace sdbus {
MethodResult::MethodResult(const MethodCall& msg, sdbus::internal::Object& object)
: call_(msg)
, object_(&object)
{
}
void MethodResult::send(const MethodReply& reply) const
{
assert(object_ != nullptr);
object_->sendReplyAsynchronously(reply);
}
}
+44 -15
View File
@@ -27,6 +27,7 @@
#include <sdbus-c++/IConnection.h>
#include <sdbus-c++/Message.h>
#include <sdbus-c++/Error.h>
#include <sdbus-c++/MethodResult.h>
#include "IConnection.h"
#include "VTableUtils.h"
#include <systemd/sd-bus.h>
@@ -48,9 +49,36 @@ void Object::registerMethod( const std::string& interfaceName
{
SDBUS_THROW_ERROR_IF(!methodCallback, "Invalid method callback provided", EINVAL);
auto& interface = interfaces_[interfaceName];
auto syncCallback = [callback = std::move(methodCallback)](MethodCall& msg)
{
auto reply = msg.createReply();
callback(msg, reply);
reply.send();
};
InterfaceData::MethodData methodData{inputSignature, outputSignature, std::move(methodCallback)};
auto& interface = interfaces_[interfaceName];
InterfaceData::MethodData methodData{inputSignature, outputSignature, std::move(syncCallback)};
auto inserted = interface.methods_.emplace(methodName, std::move(methodData)).second;
SDBUS_THROW_ERROR_IF(!inserted, "Failed to register method: method already exists", EINVAL);
}
void Object::registerMethod( const std::string& interfaceName
, const std::string& methodName
, const std::string& inputSignature
, const std::string& outputSignature
, async_method_callback asyncMethodCallback )
{
SDBUS_THROW_ERROR_IF(!asyncMethodCallback, "Invalid method callback provided", EINVAL);
auto asyncCallback = [this, callback = std::move(asyncMethodCallback)](MethodCall& msg)
{
MethodResult result{msg, *this};
callback(msg, result);
};
auto& interface = interfaces_[interfaceName];
InterfaceData::MethodData methodData{inputSignature, outputSignature, std::move(asyncCallback)};
auto inserted = interface.methods_.emplace(methodName, std::move(methodData)).second;
SDBUS_THROW_ERROR_IF(!inserted, "Failed to register method: method already exists", EINVAL);
@@ -108,17 +136,24 @@ void Object::finishRegistration()
}
}
sdbus::Message Object::createSignal(const std::string& interfaceName, const std::string& signalName)
sdbus::Signal Object::createSignal(const std::string& interfaceName, const std::string& signalName)
{
// Tell, don't ask
return connection_.createSignal(objectPath_, interfaceName, signalName);
}
void Object::emitSignal(const sdbus::Message& message)
void Object::emitSignal(const sdbus::Signal& message)
{
// TODO: Make signal emitting asynchronous. Now signal can probably be emitted only from user code
// handled within the D-Bus processing loop thread, but not from any thread. In principle it will
// be the same as async replies.
message.send();
}
void Object::sendReplyAsynchronously(const MethodReply& reply)
{
connection_.sendReplyAsynchronously(reply);
}
const std::vector<sd_bus_vtable>& Object::createInterfaceVTable(InterfaceData& interfaceData)
{
auto& vtable = interfaceData.vtable_;
@@ -190,27 +225,22 @@ void Object::activateInterfaceVTable( const std::string& interfaceName
int Object::sdbus_method_callback(sd_bus_message *sdbusMessage, void *userData, sd_bus_error *retError)
{
Message message(sdbusMessage, Message::Type::eMethodCall);
MethodCall message(sdbusMessage);
auto* object = static_cast<Object*>(userData);
// Note: The lookup can be optimized by using sorted vectors instead of associative containers
auto& callback = object->interfaces_[message.getInterfaceName()].methods_[message.getMemberName()].callback_;
assert(callback);
auto reply = message.createReply();
try
{
callback(message, reply);
callback(message);
}
catch (const sdbus::Error& e)
{
sd_bus_error_set(retError, e.getName().c_str(), e.getMessage().c_str());
return 1;
}
reply.send();
return 1;
}
@@ -222,7 +252,7 @@ int Object::sdbus_property_get_callback( sd_bus */*bus*/
, void *userData
, sd_bus_error *retError )
{
Message reply(sdbusReply, Message::Type::ePlainMessage);
Message reply(sdbusReply);
auto* object = static_cast<Object*>(userData);
// Note: The lookup can be optimized by using sorted vectors instead of associative containers
@@ -254,7 +284,7 @@ int Object::sdbus_property_set_callback( sd_bus */*bus*/
, void *userData
, sd_bus_error *retError )
{
Message value(sdbusValue, Message::Type::ePlainMessage);
Message value(sdbusValue);
auto* object = static_cast<Object*>(userData);
// Note: The lookup can be optimized by using sorted vectors instead of associative containers
@@ -268,7 +298,6 @@ int Object::sdbus_property_set_callback( sd_bus */*bus*/
catch (const sdbus::Error& e)
{
sd_bus_error_set(retError, e.getName().c_str(), e.getMessage().c_str());
return 1;
}
return 1;
+12 -3
View File
@@ -32,6 +32,7 @@
#include <string>
#include <map>
#include <vector>
#include <functional>
#include <memory>
#include <cassert>
@@ -50,6 +51,12 @@ namespace internal {
, const std::string& outputSignature
, method_callback methodCallback ) override;
void registerMethod( const std::string& interfaceName
, const std::string& methodName
, const std::string& inputSignature
, const std::string& outputSignature
, async_method_callback asyncMethodCallback ) override;
void registerSignal( const std::string& interfaceName
, const std::string& signalName
, const std::string& signature ) override;
@@ -67,8 +74,10 @@ namespace internal {
void finishRegistration() override;
sdbus::Message createSignal(const std::string& interfaceName, const std::string& signalName) override;
void emitSignal(const sdbus::Message& message) override;
sdbus::Signal createSignal(const std::string& interfaceName, const std::string& signalName) override;
void emitSignal(const sdbus::Signal& message) override;
void sendReplyAsynchronously(const MethodReply& reply);
private:
using InterfaceName = std::string;
@@ -79,7 +88,7 @@ namespace internal {
{
std::string inputArgs_;
std::string outputArgs_;
method_callback callback_;
std::function<void(MethodCall&)> callback_;
};
std::map<MethodName, MethodData> methods_;
using SignalName = std::string;
+3 -3
View File
@@ -60,13 +60,13 @@ ObjectProxy::~ObjectProxy()
signalConnection_->leaveProcessingLoop();
}
Message ObjectProxy::createMethodCall(const std::string& interfaceName, const std::string& methodName)
MethodCall ObjectProxy::createMethodCall(const std::string& interfaceName, const std::string& methodName)
{
// Tell, don't ask
return connection_->createMethodCall(destination_, objectPath_, interfaceName, methodName);
}
Message ObjectProxy::callMethod(const Message& message)
MethodReply ObjectProxy::callMethod(const MethodCall& message)
{
return message.send();
}
@@ -138,7 +138,7 @@ void ObjectProxy::registerSignalHandlers(sdbus::internal::IConnection& connectio
int ObjectProxy::sdbus_signal_callback(sd_bus_message *sdbusMessage, void *userData, sd_bus_error */*retError*/)
{
Message message(sdbusMessage, Message::Type::eSignal);
Signal message(sdbusMessage);
auto* object = static_cast<ObjectProxy*>(userData);
// Note: The lookup can be optimized by using sorted vectors instead of associative containers
+2 -2
View File
@@ -52,8 +52,8 @@ namespace internal {
, std::string objectPath );
~ObjectProxy();
Message createMethodCall(const std::string& interfaceName, const std::string& methodName) override;
Message callMethod(const Message& message) override;
MethodCall createMethodCall(const std::string& interfaceName, const std::string& methodName) override;
MethodReply callMethod(const MethodCall& message) override;
void registerSignalHandler( const std::string& interfaceName
, const std::string& signalName