refactor: use async tag to denote async calls or operations

This commit is contained in:
Stanislav Angelovic
2023-12-30 22:06:00 +01:00
parent f7afe3d1b1
commit 106500a555
16 changed files with 115 additions and 103 deletions

View File

@ -445,7 +445,7 @@ On the **server** side, we generally need to create D-Bus objects and publish th
* its internal event loop
* either in a blocking way, through `enterEventLoop()`,
* or in a non-blocking async way, through `enterEventLoopAsync()`,
* or in a non-blocking async way, through `enterEventLoop(sdbus::async_t)`,
* or an external event loop. This is suitable if we use in our application an event loop implementation of our choice (e.g., sd-event, GLib Event Loop, boost::asio, ...) and we want to hook up our sdbus-c++ connections with it. See [Using sdbus-c++ in external event loops](#using-sdbus-c-in-external-event-loops) section for more information.
The object takes the D-Bus connection as a reference in its constructor. This is the only way to wire the connection and the object together. We must make sure the connection exists as long as objects using it exist.
@ -475,7 +475,7 @@ On the **client** side we likewise need a connection -- just that unlike on the
#### Stopping internal I/O event loops graciously
A connection with an asynchronous event loop (i.e. one initiated through `enterEventLoopAsync()`) will stop and join its event loop thread automatically in its destructor. An event loop that blocks in the synchronous `enterEventLoop()` call can be unblocked through `leaveEventLoop()` call on the respective bus connection issued from a different thread or from an OS signal handler.
A connection with an asynchronous event loop (i.e. one initiated through `enterEventLoop(async_t)`) will stop and join its event loop thread automatically in its destructor. An event loop that blocks in the synchronous `enterEventLoop()` call can be unblocked through `leaveEventLoop()` call on the respective bus connection issued from a different thread or from an OS signal handler.
Implementing the Concatenator example using convenience sdbus-c++ API layer
---------------------------------------------------------------------------
@ -1192,7 +1192,7 @@ Another option is to use `std::future`-based overload of the `IProxy::callMethod
### Convenience API
On the convenience API level, the call statement starts with `callMethodAsync()`, and one option is to finish the statement with `uponReplyInvoke()` that takes a callback handler. The callback is a void-returning function that takes at least one argument: pointer to the `sdbus::Error` instance. All subsequent arguments shall exactly reflect the D-Bus method output arguments. A concatenator example:
On the convenience API level, the call statement starts with `callMethod()` overload with `async_t` tag parameter, and one option is to finish the statement with `uponReplyInvoke()` that takes a callback handler. The callback is a void-returning function that takes at least one argument: pointer to the `sdbus::Error` instance. All subsequent arguments shall exactly reflect the D-Bus method output arguments. A concatenator example:
```c++
int main(int argc, char *argv[])
@ -1206,16 +1206,18 @@ int main(int argc, char *argv[])
else // We got a D-Bus error...
std::cerr << "Got concatenate error " << error->getName() << " with message " << error->getMessage() << std::endl;
}
using sdbus::async;
// Invoke concatenate on given interface of the object
{
concatenatorProxy->callMethodAsync("concatenate").onInterface(interfaceName).withArguments(numbers, separator).uponReplyInvoke(callback);
concatenatorProxy->callMethod("concatenate", async).onInterface(interfaceName).withArguments(numbers, separator).uponReplyInvoke(callback);
// When the reply comes, we shall get "Got concatenate result 1:2:3" on the standard output
}
// Invoke concatenate again, this time with no numbers and we shall get an error
{
concatenatorProxy->callMethodAsync("concatenate").onInterface(interfaceName).withArguments(std::vector<int>{}, separator).uponReplyInvoke(callback);
concatenatorProxy->callMethod("concatenate", async).onInterface(interfaceName).withArguments(std::vector<int>{}, separator).uponReplyInvoke(callback);
// When the reply comes, we shall get concatenation error message on the standard error output
}
@ -1233,7 +1235,7 @@ The future object will contain void for a void-returning D-Bus method, a single
```c++
...
auto future = concatenatorProxy->callMethodAsync("concatenate").onInterface(interfaceName).withArguments(numbers, separator).getResultAsFuture<std::string>();
auto future = concatenatorProxy->callMethod("concatenate", sdbus::async).onInterface(interfaceName).withArguments(numbers, separator).getResultAsFuture<std::string>();
try
{
auto concatenatedString = future.get(); // This waits for the reply
@ -1320,7 +1322,7 @@ We read property value easily through `IProxy::getProperty()` method:
uint32_t status = proxy->getProperty("status").onInterface("org.sdbuscpp.Concatenator");
```
Getting a property in asynchronous manner is also possible, in both callback-based and future-based way, by calling `IProxy::getPropertyAsync()` method:
Getting a property in asynchronous manner is also possible, in both callback-based and future-based way, by calling `IProxy::getProperty()` method overload with `async_t` tag parameter:
```c++
// Callback-based method:
@ -1328,9 +1330,9 @@ auto callback = [](const sdbus::Error* err, sdbus::Variant value)
{
std::cout << "Got property value: " << value.get<uint32_t>() << std::endl;
};
uint32_t status = proxy->getPropertyAsync("status").onInterface("org.sdbuscpp.Concatenator").uponReplyInvoke(std::move(callback));
uint32_t status = proxy->getProperty("status", sdbus::async).onInterface("org.sdbuscpp.Concatenator").uponReplyInvoke(std::move(callback));
// Future-based method:
std::future<sdbus::Variant> statusFuture = object.getPropertyAsync("status").onInterface("org.sdbuscpp.Concatenator").getResultAsFuture();
std::future<sdbus::Variant> statusFuture = object.getProperty("status", sdbus::async).onInterface("org.sdbuscpp.Concatenator").getResultAsFuture();
...
std::cout << "Got property value: " << statusFuture.get().get<uint32_t>() << std::endl;
```
@ -1346,14 +1348,14 @@ uint32_t status = ...;
proxy->setProperty("status").onInterface("org.sdbuscpp.Concatenator").toValue(status);
```
Setting a property in asynchronous manner is also possible, in both callback-based and future-based way, by calling `IProxy::setPropertyAsync()` method:
Setting a property in asynchronous manner is also possible, in both callback-based and future-based way, by calling `IProxy::setProperty()` method overload with `async_t` tag parameter:
```c++
// Callback-based method:
auto callback = [](const sdbus::Error* err) { /*... Error handling in case err is non-null...*/ };
uint32_t status = proxy->setPropertyAsync("status").onInterface("org.sdbuscpp.Concatenator").toValue(status).uponReplyInvoke(std::move(callback));
uint32_t status = proxy->setProperty("status", sdbus::async).onInterface("org.sdbuscpp.Concatenator").toValue(status).uponReplyInvoke(std::move(callback));
// Future-based method:
std::future<void> statusFuture = object.setPropertyAsync("status").onInterface("org.sdbuscpp.Concatenator").getResultAsFuture();
std::future<void> statusFuture = object.setProperty("status", sdbus::async).onInterface("org.sdbuscpp.Concatenator").getResultAsFuture();
```
More information on `error` callback handler parameter, on behavior of `future` in erroneous situations, can be found in section [Asynchronous client-side methods](#asynchronous-client-side-methods).
@ -1479,7 +1481,7 @@ public:
// getting the property value
sdbus::PendingAsyncCall status()
{
return object_->getPropertyAsync("status").onInterface(INTERFACE_NAME).uponReplyInvoke([this](const sdbus::Error* error, const sdbus::Variant& value){ this->onActionPropertyGetReply(value.get<uint32_t>(), error); });
return object_->getProperty("status", sdbus::async).onInterface(INTERFACE_NAME).uponReplyInvoke([this](const sdbus::Error* error, const sdbus::Variant& value){ this->onActionPropertyGetReply(value.get<uint32_t>(), error); });
}
// setting the property value
@ -1691,11 +1693,11 @@ int main(int argc, char *argv[])
{
serverConnection = sdbus::createServerBus(fds[0]);
// This is necessary so that createDirectBusConnection() below does not block
serverConnection->enterEventLoopAsync();
serverConnection->enterEventLoop(sdbus::async);
});
clientConnection = sdbus::createDirectBusConnection(fds[1]);
clientConnection->enterEventLoopAsync();
clientConnection->enterEventLoop(sdbus::async);
t.join();

View File

@ -83,7 +83,7 @@ int main()
{
auto connection = sdbus::createSessionBusConnection();
connection->requestName("org.sdbuscpp.examplemanager");
connection->enterEventLoopAsync();
connection->enterEventLoop(sdbus::async);
auto manager = std::make_unique<ManagerAdaptor>(*connection, "/org/sdbuscpp/examplemanager");
while (true)

View File

@ -407,7 +407,7 @@ namespace sdbus {
assert(interfaceName_ != nullptr); // onInterface() must be placed/called prior to this function
return proxy_.callMethodAsync("Get")
return proxy_.callMethod("Get", async)
.onInterface("org.freedesktop.DBus.Properties")
.withArguments(*interfaceName_, propertyName_)
.uponReplyInvoke(std::forward<_Function>(callback));
@ -417,7 +417,7 @@ namespace sdbus {
{
assert(interfaceName_ != nullptr); // onInterface() must be placed/called prior to this function
return proxy_.callMethodAsync("Get")
return proxy_.callMethod("Get", async)
.onInterface("org.freedesktop.DBus.Properties")
.withArguments(*interfaceName_, propertyName_)
.getResultAsFuture<Variant>();
@ -508,7 +508,7 @@ namespace sdbus {
assert(interfaceName_ != nullptr); // onInterface() must be placed/called prior to this function
return proxy_.callMethodAsync("Set")
return proxy_.callMethod("Set", async)
.onInterface("org.freedesktop.DBus.Properties")
.withArguments(*interfaceName_, propertyName_, std::move(value_))
.uponReplyInvoke(std::forward<_Function>(callback));
@ -518,7 +518,7 @@ namespace sdbus {
{
assert(interfaceName_ != nullptr); // onInterface() must be placed/called prior to this function
return proxy_.callMethodAsync("Set")
return proxy_.callMethod("Set", async)
.onInterface("org.freedesktop.DBus.Properties")
.withArguments(*interfaceName_, propertyName_, std::move(value_))
.getResultAsFuture<>();
@ -567,7 +567,7 @@ namespace sdbus {
assert(interfaceName_ != nullptr); // onInterface() must be placed/called prior to this function
return proxy_.callMethodAsync("GetAll")
return proxy_.callMethod("GetAll", async)
.onInterface("org.freedesktop.DBus.Properties")
.withArguments(*interfaceName_)
.uponReplyInvoke(std::forward<_Function>(callback));
@ -577,7 +577,7 @@ namespace sdbus {
{
assert(interfaceName_ != nullptr); // onInterface() must be placed/called prior to this function
return proxy_.callMethodAsync("GetAll")
return proxy_.callMethod("GetAll", async)
.onInterface("org.freedesktop.DBus.Properties")
.withArguments(*interfaceName_)
.getResultAsFuture<std::map<std::string, Variant>>();

View File

@ -100,7 +100,7 @@ namespace sdbus {
* The same as enterEventLoop, except that it doesn't block
* because it runs the loop in a separate, internally managed thread.
*/
virtual void enterEventLoopAsync() = 0;
virtual void enterEventLoop(async_t) = 0;
/*!
* @brief Leaves the I/O event loop running on this bus connection
@ -204,7 +204,7 @@ namespace sdbus {
*
* You don't need to directly call this method or getEventLoopPollData() method
* when using convenient, internal bus connection event loops through
* enterEventLoop() or enterEventLoopAsync() calls, or when the bus is
* enterEventLoop() or enterEventLoop(async) calls, or when the bus is
* connected to an sd-event event loop through attachSdEventLoop().
* It is invoked automatically when necessary.
*
@ -334,7 +334,7 @@ namespace sdbus {
*
* @throws sdbus::Error in case of failure
*/
[[nodiscard]] virtual Slot addMatchAsync(const std::string& match, message_handler callback, message_handler installCallback) = 0;
[[nodiscard]] virtual Slot addMatch(const std::string& match, message_handler callback, message_handler installCallback, async_t) = 0;
/*!
* @brief Asynchronously installs a floating match rule for messages received on this bus connection
@ -352,7 +352,9 @@ namespace sdbus {
*
* @throws sdbus::Error in case of failure
*/
virtual void addMatchAsync(const std::string& match, message_handler callback, message_handler installCallback, floating_slot_t) = 0;
virtual void addMatch(const std::string& match, message_handler callback, message_handler installCallback, async_t, floating_slot_t) = 0;
// TODO: addMatchAsync with std::future support?
/*!
* @copydoc IConnection::enterEventLoop()
@ -362,11 +364,11 @@ namespace sdbus {
[[deprecated("This function has been replaced by enterEventLoop()")]] void enterProcessingLoop();
/*!
* @copydoc IConnection::enterEventLoopAsync()
* @copydoc IConnection::enterEventLoop(sdbus::async_t)
*
* @deprecated This function has been replaced by enterEventLoopAsync()
* @deprecated This function has been replaced by enterEventLoop(async_t)
*/
[[deprecated("This function has been replaced by enterEventLoopAsync()")]] void enterProcessingLoopAsync();
[[deprecated("This function has been replaced by enterEventLoop(async_t)")]] void enterProcessingLoopAsync();
/*!
* @copydoc IConnection::leaveEventLoop()
@ -446,7 +448,7 @@ namespace sdbus {
inline void IConnection::enterProcessingLoopAsync()
{
enterEventLoopAsync();
enterEventLoop(async);
}
inline void IConnection::leaveProcessingLoop()

View File

@ -272,15 +272,15 @@ namespace sdbus {
* Example of use:
* @code
* int a = ..., b = ...;
* object_.callMethodAsync("multiply").onInterface(INTERFACE_NAME).withArguments(a, b).uponReplyInvoke([](int result)
* object_.callMethod("multiply").onInterface(INTERFACE_NAME).withArguments(a, b).uponReplyInvoke([](int result)
* {
* std::cout << "Got result of multiplying " << a << " and " << b << ": " << result << std::endl;
* });
* }, sdbus::async);
* @endcode
*
* @throws sdbus::Error in case of failure
*/
[[nodiscard]] AsyncMethodInvoker callMethodAsync(const std::string& methodName);
[[nodiscard]] AsyncMethodInvoker callMethod(const std::string& methodName, async_t);
/*!
* @brief Registers signal handler for a given signal of the D-Bus object
@ -335,14 +335,14 @@ namespace sdbus {
*
* Example of use:
* @code
* std::future<sdbus::Variant> state = object.getPropertyAsync("state").onInterface("com.kistler.foo").getResultAsFuture();
* std::future<sdbus::Variant> state = object.getProperty("state", sdbus::async).onInterface("com.kistler.foo").getResultAsFuture();
* auto callback = [](const sdbus::Error* err, const sdbus::Variant& value){ ... };
* object.getPropertyAsync("state").onInterface("com.kistler.foo").uponReplyInvoke(std::move(callback));
* object.getProperty("state", sdbus::async).onInterface("com.kistler.foo").uponReplyInvoke(std::move(callback));
* @endcode
*
* @throws sdbus::Error in case of failure
*/
[[nodiscard]] AsyncPropertyGetter getPropertyAsync(const std::string& propertyName);
[[nodiscard]] AsyncPropertyGetter getProperty(const std::string& propertyName, async_t);
/*!
* @brief Sets value of a property of the D-Bus object
@ -379,12 +379,12 @@ namespace sdbus {
* @code
* int state = ...;
* // We can wait until the set operation finishes by waiting on the future
* std::future<void> res = object_.setPropertyAsync("state").onInterface("com.kistler.foo").toValue(state).getResultAsFuture();
* std::future<void> res = object_.setProperty("state", sdbus::async).onInterface("com.kistler.foo").toValue(state).getResultAsFuture();
* @endcode
*
* @throws sdbus::Error in case of failure
*/
[[nodiscard]] AsyncPropertySetter setPropertyAsync(const std::string& propertyName);
[[nodiscard]] AsyncPropertySetter setProperty(const std::string& propertyName, async_t);
/*!
* @brief Gets values of all properties of the D-Bus object
@ -414,12 +414,12 @@ namespace sdbus {
* Example of use:
* @code
* auto callback = [](const sdbus::Error* err, const std::map<std::string, Variant>>& properties){ ... };
* auto props = object.getAllPropertiesAsync().onInterface("com.kistler.foo").uponReplyInvoke(std::move(callback));
* auto props = object.getAllProperties(sdbus::async).onInterface("com.kistler.foo").uponReplyInvoke(std::move(callback));
* @endcode
*
* @throws sdbus::Error in case of failure
*/
[[nodiscard]] AsyncAllPropertiesGetter getAllPropertiesAsync();
[[nodiscard]] AsyncAllPropertiesGetter getAllProperties(async_t);
/*!
* @brief Provides D-Bus connection used by the proxy
@ -521,7 +521,7 @@ namespace sdbus {
return MethodInvoker(*this, methodName);
}
inline AsyncMethodInvoker IProxy::callMethodAsync(const std::string& methodName)
inline AsyncMethodInvoker IProxy::callMethod(const std::string& methodName, async_t)
{
return AsyncMethodInvoker(*this, methodName);
}
@ -536,7 +536,7 @@ namespace sdbus {
return PropertyGetter(*this, propertyName);
}
inline AsyncPropertyGetter IProxy::getPropertyAsync(const std::string& propertyName)
inline AsyncPropertyGetter IProxy::getProperty(const std::string& propertyName, async_t)
{
return AsyncPropertyGetter(*this, propertyName);
}
@ -546,7 +546,7 @@ namespace sdbus {
return PropertySetter(*this, propertyName);
}
inline AsyncPropertySetter IProxy::setPropertyAsync(const std::string& propertyName)
inline AsyncPropertySetter IProxy::setProperty(const std::string& propertyName, async_t)
{
return AsyncPropertySetter(*this, propertyName);
}
@ -556,7 +556,7 @@ namespace sdbus {
return AllPropertiesGetter(*this);
}
inline AsyncAllPropertiesGetter IProxy::getAllPropertiesAsync()
inline AsyncAllPropertiesGetter IProxy::getAllProperties(async_t)
{
return AsyncAllPropertiesGetter(*this);
}

View File

@ -151,14 +151,14 @@ namespace sdbus {
}
template <typename _Function>
PendingAsyncCall GetAsync(const std::string& interfaceName, const std::string& propertyName, _Function&& callback)
PendingAsyncCall Get(const std::string& interfaceName, const std::string& propertyName, _Function&& callback, async_t)
{
return proxy_->getPropertyAsync(propertyName).onInterface(interfaceName).uponReplyInvoke(std::forward<_Function>(callback));
return proxy_->getProperty(propertyName, async).onInterface(interfaceName).uponReplyInvoke(std::forward<_Function>(callback));
}
std::future<sdbus::Variant> GetAsync(const std::string& interfaceName, const std::string& propertyName, with_future_t)
std::future<sdbus::Variant> Get(const std::string& interfaceName, const std::string& propertyName, async_t, with_future_t)
{
return proxy_->getPropertyAsync(propertyName).onInterface(interfaceName).getResultAsFuture();
return proxy_->getProperty(propertyName, async).onInterface(interfaceName).getResultAsFuture();
}
void Set(const std::string& interfaceName, const std::string& propertyName, const sdbus::Variant& value)
@ -172,14 +172,14 @@ namespace sdbus {
}
template <typename _Function>
PendingAsyncCall SetAsync(const std::string& interfaceName, const std::string& propertyName, const sdbus::Variant& value, _Function&& callback)
PendingAsyncCall Set(const std::string& interfaceName, const std::string& propertyName, const sdbus::Variant& value, _Function&& callback, async_t)
{
return proxy_->setPropertyAsync(propertyName).onInterface(interfaceName).toValue(value).uponReplyInvoke(std::forward<_Function>(callback));
return proxy_->setProperty(propertyName, async).onInterface(interfaceName).toValue(value).uponReplyInvoke(std::forward<_Function>(callback));
}
std::future<void> SetAsync(const std::string& interfaceName, const std::string& propertyName, const sdbus::Variant& value, with_future_t)
std::future<void> Set(const std::string& interfaceName, const std::string& propertyName, const sdbus::Variant& value, async_t, with_future_t)
{
return proxy_->setPropertyAsync(propertyName).onInterface(interfaceName).toValue(value).getResultAsFuture();
return proxy_->setProperty(propertyName, async).onInterface(interfaceName).toValue(value).getResultAsFuture();
}
std::map<std::string, sdbus::Variant> GetAll(const std::string& interfaceName)
@ -188,14 +188,14 @@ namespace sdbus {
}
template <typename _Function>
PendingAsyncCall GetAllAsync(const std::string& interfaceName, _Function&& callback)
PendingAsyncCall GetAll(const std::string& interfaceName, _Function&& callback, async_t)
{
return proxy_->getAllPropertiesAsync().onInterface(interfaceName).uponReplyInvoke(std::forward<_Function>(callback));
return proxy_->getAllProperties(async).onInterface(interfaceName).uponReplyInvoke(std::forward<_Function>(callback));
}
std::future<std::map<std::string, sdbus::Variant>> GetAllAsync(const std::string& interfaceName, with_future_t)
std::future<std::map<std::string, sdbus::Variant>> GetAll(const std::string& interfaceName, async_t, with_future_t)
{
return proxy_->getAllPropertiesAsync().onInterface(interfaceName).getResultAsFuture();
return proxy_->getAllProperties(async).onInterface(interfaceName).getResultAsFuture();
}
private:

View File

@ -72,6 +72,12 @@ namespace sdbus {
// Type-erased RAII-style handle to callbacks/subscriptions registered to sdbus-c++
using Slot = std::unique_ptr<void, std::function<void(void*)>>;
// Tag denoting an asynchronous call or operation
struct async_t { explicit async_t() = default; };
inline constexpr async_t async{};
// Tag denoting a variant of an asynchronous method call that returns std::future instead of accepting
struct with_future_t { explicit with_future_t() = default; };
inline constexpr with_future_t with_future{};
// Tag specifying that an owning slot handle shall be returned from a registration/subscription function to the caller
struct return_slot_t { explicit return_slot_t() = default; };
inline constexpr return_slot_t return_slot{};
@ -88,9 +94,6 @@ namespace sdbus {
// Such proxies are typically created to carry out a simple synchronous D-Bus call(s) and then are destroyed.
struct dont_run_event_loop_thread_t { explicit dont_run_event_loop_thread_t() = default; };
inline constexpr dont_run_event_loop_thread_t dont_run_event_loop_thread{};
// Tag denoting an asynchronous call that returns std::future as a handle
struct with_future_t { explicit with_future_t() = default; };
inline constexpr with_future_t with_future{};
// Tag denoting a call where the reply shouldn't be waited for
struct dont_expect_reply_t { explicit dont_expect_reply_t() = default; };
inline constexpr dont_expect_reply_t dont_expect_reply{};

View File

@ -151,7 +151,7 @@ void Connection::enterEventLoop()
}
}
void Connection::enterEventLoopAsync()
void Connection::enterEventLoop(async_t)
{
if (!asyncLoopThread_.joinable())
asyncLoopThread_ = std::thread([this](){ enterEventLoop(); });
@ -247,7 +247,7 @@ void Connection::addMatch(const std::string& match, message_handler callback, fl
floatingMatchRules_.push_back(addMatch(match, std::move(callback)));
}
Slot Connection::addMatchAsync(const std::string& match, message_handler callback, message_handler installCallback)
Slot Connection::addMatch(const std::string& match, message_handler callback, message_handler installCallback, async_t)
{
SDBUS_THROW_ERROR_IF(!callback, "Invalid match callback handler provided", EINVAL);
@ -268,9 +268,9 @@ Slot Connection::addMatchAsync(const std::string& match, message_handler callbac
return {matchInfo.release(), [](void *ptr){ delete static_cast<MatchInfo*>(ptr); }};
}
void Connection::addMatchAsync(const std::string& match, message_handler callback, message_handler installCallback, floating_slot_t)
void Connection::addMatch(const std::string& match, message_handler callback, message_handler installCallback, async_t, floating_slot_t)
{
floatingMatchRules_.push_back(addMatchAsync(match, std::move(callback), std::move(installCallback)));
floatingMatchRules_.push_back(addMatch(match, std::move(callback), std::move(installCallback), async));
}
void Connection::attachSdEventLoop(sd_event *event, int priority)

View File

@ -82,7 +82,7 @@ namespace sdbus::internal {
void releaseName(const std::string& name) override;
std::string getUniqueName() const override;
void enterEventLoop() override;
void enterEventLoopAsync() override;
void enterEventLoop(async_t) override;
void leaveEventLoop() override;
PollData getEventLoopPollData() const override;
bool processPendingEvent() override;
@ -97,8 +97,8 @@ namespace sdbus::internal {
[[nodiscard]] Slot addMatch(const std::string& match, message_handler callback) override;
void addMatch(const std::string& match, message_handler callback, floating_slot_t) override;
[[nodiscard]] Slot addMatchAsync(const std::string& match, message_handler callback, message_handler installCallback) override;
void addMatchAsync(const std::string& match, message_handler callback, message_handler installCallback, floating_slot_t) override;
[[nodiscard]] Slot addMatch(const std::string& match, message_handler callback, message_handler installCallback, async_t) override;
void addMatch(const std::string& match, message_handler callback, message_handler installCallback, async_t, floating_slot_t) override;
void attachSdEventLoop(sd_event *event, int priority) override;
void detachSdEventLoop() override;

View File

@ -63,7 +63,7 @@ Proxy::Proxy( std::unique_ptr<sdbus::internal::IConnection>&& connection
// The connection is ours only, i.e. it's us who has to manage the event loop upon this connection,
// in order that we get and process signals, async call replies, and other messages from D-Bus.
connection_->enterEventLoopAsync();
connection_->enterEventLoop(async);
}
Proxy::Proxy( std::unique_ptr<sdbus::internal::IConnection>&& connection

View File

@ -92,16 +92,17 @@ TYPED_TEST(AConnection, CanInstallMatchRuleAsynchronously)
auto matchRule = "sender='" + BUS_NAME + "',path='" + OBJECT_PATH + "'";
std::atomic<bool> matchingMessageReceived{false};
std::atomic<bool> matchRuleInstalled{false};
auto slot = this->s_proxyConnection->addMatchAsync( matchRule
, [&](sdbus::Message msg)
{
if(msg.getPath() == OBJECT_PATH)
matchingMessageReceived = true;
}
, [&](sdbus::Message /*msg*/)
{
matchRuleInstalled = true;
} );
auto slot = this->s_proxyConnection->addMatch( matchRule
, [&](sdbus::Message msg)
{
if(msg.getPath() == OBJECT_PATH)
matchingMessageReceived = true;
}
, [&](sdbus::Message /*msg*/)
{
matchRuleInstalled = true;
}
, sdbus::async);
EXPECT_TRUE(waitUntil(matchRuleInstalled));
@ -131,7 +132,7 @@ TYPED_TEST(AConnection, CanAddFloatingMatchRule)
auto matchRule = "sender='" + BUS_NAME + "',path='" + OBJECT_PATH + "'";
std::atomic<bool> matchingMessageReceived{false};
auto con = sdbus::createSystemBusConnection();
con->enterEventLoopAsync();
con->enterEventLoop(sdbus::async);
auto callback = [&](sdbus::Message msg)
{
if(msg.getPath() == OBJECT_PATH)

View File

@ -81,21 +81,22 @@ TYPED_TEST(SdbusTestObject, GetsPropertyAsynchronouslyViaPropertiesInterface)
{
std::promise<std::string> promise;
auto future = promise.get_future();
this->m_proxy->GetAsync(INTERFACE_NAME, "state", [&](const sdbus::Error* err, sdbus::Variant value)
auto getCallback = [&](const sdbus::Error* err, sdbus::Variant value)
{
if (err == nullptr)
promise.set_value(value.get<std::string>());
promise.set_value(value.get<std::string>());
else
promise.set_exception(std::make_exception_ptr(*err));
});
promise.set_exception(std::make_exception_ptr(*err));
};
this->m_proxy->Get(INTERFACE_NAME, "state", std::move(getCallback), sdbus::async);
ASSERT_THAT(future.get(), Eq(DEFAULT_STATE_VALUE));
}
TYPED_TEST(SdbusTestObject, GetsPropertyAsynchronouslyViaPropertiesInterfaceWithFuture)
{
auto future = this->m_proxy->GetAsync(INTERFACE_NAME, "state", sdbus::with_future);
auto future = this->m_proxy->Get(INTERFACE_NAME, "state", sdbus::async, sdbus::with_future);
ASSERT_THAT(future.get().template get<std::string>(), Eq(DEFAULT_STATE_VALUE));
}
@ -114,14 +115,15 @@ TYPED_TEST(SdbusTestObject, SetsPropertyAsynchronouslyViaPropertiesInterface)
uint32_t newActionValue = 2346;
std::promise<void> promise;
auto future = promise.get_future();
this->m_proxy->SetAsync(INTERFACE_NAME, "action", sdbus::Variant{newActionValue}, [&](const sdbus::Error* err)
auto setCallback = [&](const sdbus::Error* err)
{
if (err == nullptr)
promise.set_value();
else
promise.set_exception(std::make_exception_ptr(*err));
});
};
this->m_proxy->Set(INTERFACE_NAME, "action", sdbus::Variant{newActionValue}, std::move(setCallback), sdbus::async);
ASSERT_NO_THROW(future.get());
ASSERT_THAT(this->m_proxy->action(), Eq(newActionValue));
@ -131,7 +133,7 @@ TYPED_TEST(SdbusTestObject, SetsPropertyAsynchronouslyViaPropertiesInterfaceWith
{
uint32_t newActionValue = 2347;
auto future = this->m_proxy->SetAsync(INTERFACE_NAME, "action", sdbus::Variant{newActionValue}, sdbus::with_future);
auto future = this->m_proxy->Set(INTERFACE_NAME, "action", sdbus::Variant{newActionValue}, sdbus::async, sdbus::with_future);
ASSERT_NO_THROW(future.get());
ASSERT_THAT(this->m_proxy->action(), Eq(newActionValue));
@ -151,14 +153,15 @@ TYPED_TEST(SdbusTestObject, GetsAllPropertiesAsynchronouslyViaPropertiesInterfac
{
std::promise<std::map<std::string, sdbus::Variant>> promise;
auto future = promise.get_future();
this->m_proxy->GetAllAsync(INTERFACE_NAME, [&](const sdbus::Error* err, std::map<std::string, sdbus::Variant> value)
auto getCallback = [&](const sdbus::Error* err, std::map<std::string, sdbus::Variant> value)
{
if (err == nullptr)
promise.set_value(std::move(value));
else
promise.set_exception(std::make_exception_ptr(*err));
});
};
this->m_proxy->GetAll(INTERFACE_NAME, std::move(getCallback), sdbus::async);
const auto properties = future.get();
ASSERT_THAT(properties, SizeIs(3));
@ -169,7 +172,7 @@ TYPED_TEST(SdbusTestObject, GetsAllPropertiesAsynchronouslyViaPropertiesInterfac
TYPED_TEST(SdbusTestObject, GetsAllPropertiesAsynchronouslyViaPropertiesInterfaceWithFuture)
{
auto future = this->m_proxy->GetAllAsync(INTERFACE_NAME, sdbus::with_future);
auto future = this->m_proxy->GetAll(INTERFACE_NAME, sdbus::async, sdbus::with_future);
auto properties = future.get();

View File

@ -102,8 +102,8 @@ public:
static void SetUpTestCase()
{
BaseTestFixture::SetUpTestCase();
s_proxyConnection->enterEventLoopAsync();
s_adaptorConnection->enterEventLoopAsync();
s_proxyConnection->enterEventLoop(async);
s_adaptorConnection->enterEventLoop(async);
std::this_thread::sleep_for(std::chrono::milliseconds(50)); // Give time for the proxy connection to start listening to signals
}
@ -237,11 +237,11 @@ private:
auto fd = accept4(sock, NULL, NULL, /*SOCK_NONBLOCK|*/SOCK_CLOEXEC);
m_adaptorConnection = sdbus::createServerBus(fd);
// This is necessary so that createDirectBusConnection() below does not block
m_adaptorConnection->enterEventLoopAsync();
m_adaptorConnection->enterEventLoop(async);
});
m_proxyConnection = sdbus::createDirectBusConnection("unix:path=" + DIRECT_CONNECTION_SOCKET_PATH);
m_proxyConnection->enterEventLoopAsync();
m_proxyConnection->enterEventLoop(async);
t.join();
}

View File

@ -114,7 +114,7 @@ uint32_t TestProxy::doOperationWithTimeout(const std::chrono::microseconds &time
sdbus::PendingAsyncCall TestProxy::doOperationClientSideAsync(uint32_t param)
{
return getProxy().callMethodAsync("doOperation")
return getProxy().callMethod("doOperation", async)
.onInterface(sdbus::test::INTERFACE_NAME)
.withArguments(param)
.uponReplyInvoke([this](const sdbus::Error* error, uint32_t returnValue)
@ -125,7 +125,7 @@ sdbus::PendingAsyncCall TestProxy::doOperationClientSideAsync(uint32_t param)
std::future<uint32_t> TestProxy::doOperationClientSideAsync(uint32_t param, with_future_t)
{
return getProxy().callMethodAsync("doOperation")
return getProxy().callMethod("doOperation", async)
.onInterface(sdbus::test::INTERFACE_NAME)
.withArguments(param)
.getResultAsFuture<uint32_t>();
@ -141,7 +141,7 @@ std::future<MethodReply> TestProxy::doOperationClientSideAsyncOnBasicAPILevel(ui
void TestProxy::doErroneousOperationClientSideAsync()
{
getProxy().callMethodAsync("throwError")
getProxy().callMethod("throwError", async)
.onInterface(sdbus::test::INTERFACE_NAME)
.uponReplyInvoke([this](const sdbus::Error* error)
{
@ -151,7 +151,7 @@ void TestProxy::doErroneousOperationClientSideAsync()
std::future<void> TestProxy::doErroneousOperationClientSideAsync(with_future_t)
{
return getProxy().callMethodAsync("throwError")
return getProxy().callMethod("throwError", async)
.onInterface(sdbus::test::INTERFACE_NAME)
.getResultAsFuture<>();
}
@ -159,7 +159,7 @@ std::future<void> TestProxy::doErroneousOperationClientSideAsync(with_future_t)
void TestProxy::doOperationClientSideAsyncWithTimeout(const std::chrono::microseconds &timeout, uint32_t param)
{
using namespace std::chrono_literals;
getProxy().callMethodAsync("doOperation")
getProxy().callMethod("doOperation", async)
.onInterface(sdbus::test::INTERFACE_NAME)
.withTimeout(timeout)
.withArguments(param)

View File

@ -44,7 +44,8 @@ protected:
public:
sdbus::PendingAsyncCall concatenate(const std::map<std::string, sdbus::Variant>& params)
{
return proxy_->callMethodAsync("concatenate").onInterface(INTERFACE_NAME).withArguments(params).uponReplyInvoke([this](const sdbus::Error* error, const std::string& result){ this->onConcatenateReply(result, error); });
using sdbus::async;
return proxy_->callMethod("concatenate", async).onInterface(INTERFACE_NAME).withArguments(params).uponReplyInvoke([this](const sdbus::Error* error, const std::string& result){ this->onConcatenateReply(result, error); });
}
private:

View File

@ -481,7 +481,7 @@ int main(int argc, char *argv[])
// We could run the loop in a sync way, but we want it to run also when proxies are destroyed for better
// coverage of multi-threaded scenarios, so we run it async and use condition variable for exit notification
//con.enterEventLoop();
con.enterEventLoopAsync();
con.enterEventLoop(sdbus::async);
std::unique_lock<std::mutex> lock(clientThreadExitMutex);
clientThreadExitCond.wait(lock, [&]{return clientThreadExit;});