diff --git a/docs/using-sdbus-c++.md b/docs/using-sdbus-c++.md index 496de97..c6513a2 100644 --- a/docs/using-sdbus-c++.md +++ b/docs/using-sdbus-c++.md @@ -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{}, separator).uponReplyInvoke(callback); + concatenatorProxy->callMethod("concatenate", async).onInterface(interfaceName).withArguments(std::vector{}, 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(); + auto future = concatenatorProxy->callMethod("concatenate", sdbus::async).onInterface(interfaceName).withArguments(numbers, separator).getResultAsFuture(); 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() << 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 statusFuture = object.getPropertyAsync("status").onInterface("org.sdbuscpp.Concatenator").getResultAsFuture(); +std::future statusFuture = object.getProperty("status", sdbus::async).onInterface("org.sdbuscpp.Concatenator").getResultAsFuture(); ... std::cout << "Got property value: " << statusFuture.get().get() << 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 statusFuture = object.setPropertyAsync("status").onInterface("org.sdbuscpp.Concatenator").getResultAsFuture(); +std::future 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(), error); }); + return object_->getProperty("status", sdbus::async).onInterface(INTERFACE_NAME).uponReplyInvoke([this](const sdbus::Error* error, const sdbus::Variant& value){ this->onActionPropertyGetReply(value.get(), 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(); diff --git a/examples/org.freedesktop.DBus.ObjectManager/obj-manager-server.cpp b/examples/org.freedesktop.DBus.ObjectManager/obj-manager-server.cpp index 4631ed5..0d73ac6 100644 --- a/examples/org.freedesktop.DBus.ObjectManager/obj-manager-server.cpp +++ b/examples/org.freedesktop.DBus.ObjectManager/obj-manager-server.cpp @@ -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(*connection, "/org/sdbuscpp/examplemanager"); while (true) diff --git a/include/sdbus-c++/ConvenienceApiClasses.inl b/include/sdbus-c++/ConvenienceApiClasses.inl index 2dc33b2..d054e42 100644 --- a/include/sdbus-c++/ConvenienceApiClasses.inl +++ b/include/sdbus-c++/ConvenienceApiClasses.inl @@ -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(); @@ -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>(); diff --git a/include/sdbus-c++/IConnection.h b/include/sdbus-c++/IConnection.h index 1065710..c64eaca 100644 --- a/include/sdbus-c++/IConnection.h +++ b/include/sdbus-c++/IConnection.h @@ -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() diff --git a/include/sdbus-c++/IProxy.h b/include/sdbus-c++/IProxy.h index f71e681..e5a2da8 100644 --- a/include/sdbus-c++/IProxy.h +++ b/include/sdbus-c++/IProxy.h @@ -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 state = object.getPropertyAsync("state").onInterface("com.kistler.foo").getResultAsFuture(); + * std::future 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 res = object_.setPropertyAsync("state").onInterface("com.kistler.foo").toValue(state).getResultAsFuture(); + * std::future 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>& 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); } diff --git a/include/sdbus-c++/StandardInterfaces.h b/include/sdbus-c++/StandardInterfaces.h index ae79c8f..05e37aa 100644 --- a/include/sdbus-c++/StandardInterfaces.h +++ b/include/sdbus-c++/StandardInterfaces.h @@ -151,14 +151,14 @@ namespace sdbus { } template - 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 GetAsync(const std::string& interfaceName, const std::string& propertyName, with_future_t) + std::future 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 - 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 SetAsync(const std::string& interfaceName, const std::string& propertyName, const sdbus::Variant& value, with_future_t) + std::future 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 GetAll(const std::string& interfaceName) @@ -188,14 +188,14 @@ namespace sdbus { } template - 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> GetAllAsync(const std::string& interfaceName, with_future_t) + std::future> GetAll(const std::string& interfaceName, async_t, with_future_t) { - return proxy_->getAllPropertiesAsync().onInterface(interfaceName).getResultAsFuture(); + return proxy_->getAllProperties(async).onInterface(interfaceName).getResultAsFuture(); } private: diff --git a/include/sdbus-c++/TypeTraits.h b/include/sdbus-c++/TypeTraits.h index 71d4aeb..13ec755 100644 --- a/include/sdbus-c++/TypeTraits.h +++ b/include/sdbus-c++/TypeTraits.h @@ -72,6 +72,12 @@ namespace sdbus { // Type-erased RAII-style handle to callbacks/subscriptions registered to sdbus-c++ using Slot = std::unique_ptr>; + // 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{}; diff --git a/src/Connection.cpp b/src/Connection.cpp index 1d757a3..8d0b977 100644 --- a/src/Connection.cpp +++ b/src/Connection.cpp @@ -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(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) diff --git a/src/Connection.h b/src/Connection.h index fef5110..69e0665 100644 --- a/src/Connection.h +++ b/src/Connection.h @@ -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; diff --git a/src/Proxy.cpp b/src/Proxy.cpp index 7044cce..49b078d 100644 --- a/src/Proxy.cpp +++ b/src/Proxy.cpp @@ -63,7 +63,7 @@ Proxy::Proxy( std::unique_ptr&& 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&& connection diff --git a/tests/integrationtests/DBusGeneralTests.cpp b/tests/integrationtests/DBusGeneralTests.cpp index c7b318b..354ee9a 100644 --- a/tests/integrationtests/DBusGeneralTests.cpp +++ b/tests/integrationtests/DBusGeneralTests.cpp @@ -92,16 +92,17 @@ TYPED_TEST(AConnection, CanInstallMatchRuleAsynchronously) auto matchRule = "sender='" + BUS_NAME + "',path='" + OBJECT_PATH + "'"; std::atomic matchingMessageReceived{false}; std::atomic 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 matchingMessageReceived{false}; auto con = sdbus::createSystemBusConnection(); - con->enterEventLoopAsync(); + con->enterEventLoop(sdbus::async); auto callback = [&](sdbus::Message msg) { if(msg.getPath() == OBJECT_PATH) diff --git a/tests/integrationtests/DBusStandardInterfacesTests.cpp b/tests/integrationtests/DBusStandardInterfacesTests.cpp index 57e9340..6db1da8 100644 --- a/tests/integrationtests/DBusStandardInterfacesTests.cpp +++ b/tests/integrationtests/DBusStandardInterfacesTests.cpp @@ -81,21 +81,22 @@ TYPED_TEST(SdbusTestObject, GetsPropertyAsynchronouslyViaPropertiesInterface) { std::promise 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()); + promise.set_value(value.get()); 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(), Eq(DEFAULT_STATE_VALUE)); } @@ -114,14 +115,15 @@ TYPED_TEST(SdbusTestObject, SetsPropertyAsynchronouslyViaPropertiesInterface) uint32_t newActionValue = 2346; std::promise 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> promise; auto future = promise.get_future(); - - this->m_proxy->GetAllAsync(INTERFACE_NAME, [&](const sdbus::Error* err, std::map value) + auto getCallback = [&](const sdbus::Error* err, std::map 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(); diff --git a/tests/integrationtests/TestFixture.h b/tests/integrationtests/TestFixture.h index 914b782..08759c5 100644 --- a/tests/integrationtests/TestFixture.h +++ b/tests/integrationtests/TestFixture.h @@ -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(); } diff --git a/tests/integrationtests/TestProxy.cpp b/tests/integrationtests/TestProxy.cpp index 5e07929..48d2346 100644 --- a/tests/integrationtests/TestProxy.cpp +++ b/tests/integrationtests/TestProxy.cpp @@ -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 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(); @@ -141,7 +141,7 @@ std::future 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 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 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) diff --git a/tests/stresstests/concatenator-proxy.h b/tests/stresstests/concatenator-proxy.h index 8aa14be..2f4056a 100644 --- a/tests/stresstests/concatenator-proxy.h +++ b/tests/stresstests/concatenator-proxy.h @@ -44,7 +44,8 @@ protected: public: sdbus::PendingAsyncCall concatenate(const std::map& 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: diff --git a/tests/stresstests/sdbus-c++-stress-tests.cpp b/tests/stresstests/sdbus-c++-stress-tests.cpp index 2a4b1d3..f5393d9 100644 --- a/tests/stresstests/sdbus-c++-stress-tests.cpp +++ b/tests/stresstests/sdbus-c++-stress-tests.cpp @@ -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 lock(clientThreadExitMutex); clientThreadExitCond.wait(lock, [&]{return clientThreadExit;});