diff --git a/docs/using-sdbus-c++.md b/docs/using-sdbus-c++.md index 6fc4b58..975907d 100644 --- a/docs/using-sdbus-c++.md +++ b/docs/using-sdbus-c++.md @@ -317,7 +317,7 @@ int main(int argc, char *argv[]) We establish a D-Bus system connection and request `org.sdbuscpp.concatenator` D-Bus name on it. This name will be used by D-Bus clients to find the service. We then create an object with path `/org/sdbuscpp/concatenator` on this connection. We add a so-called object vtable, where we declare and describe its D-Bus API, i.e. its interface, methods, signals, properties (if any) that the object provides. Then we need to make sure to run the event loop upon the connection, which handles all incoming, outgoing and other requests. -> **_Tip_:** There's also an overload of `addVTable()` method with `request_slot_t` tag parameter which returns a `Slot` object. The slot is a simple RAII-based handle of the associated vtable registration. As long as you keep the slot object, the vtable registration is active. When you let go of the slot, the vtable is automatically removed from the D-Bus object. This gives you the ability to implement "dynamic" D-Bus object API that is addable as well as removable at any time during object lifetime. +> **_Tip_:** There's also an overload of `addVTable()` method with `return_slot_t` tag parameter which returns a `Slot` object. The slot is a simple RAII-based handle of the associated vtable registration. As long as you keep the slot object, the vtable registration is active. When you let go of the slot, the vtable is automatically removed from the D-Bus object. This gives you the ability to implement "dynamic" D-Bus object API that is addable as well as removable at any time during object lifetime. > **_Note_:** A D-Bus object can have any number of vtables attached to it. Even a D-Bus interface of an object can have multiple vtables attached to it. @@ -394,7 +394,7 @@ In simple cases, we don't need to create D-Bus connection explicitly for our pro The callback for a D-Bus signal handler on this level is any callable of signature `void(sdbus::Signal signal)`. The one and only parameter `signal` is the incoming signal message. We need to deserialize arguments from it, and then we can do our business logic with it. -> **_Tip_:** There's also an overload of `registerSignalHandler()` with `request_slot_t` tag which returns a `Slot` object. The slot is a simple RAII-based handle of the subscription. As long as you keep the slot object, the signal subscription is active. When you let go of the object, the signal handler is automatically unregistered. This gives you finer control over the lifetime of signal subscription. +> **_Tip_:** There's also an overload of `registerSignalHandler()` with `return_slot_t` tag which returns a `Slot` object. The slot is a simple RAII-based handle of the subscription. As long as you keep the slot object, the signal subscription is active. When you let go of the object, the signal handler is automatically unregistered. This gives you finer control over the lifetime of signal subscription. Subsequently, we invoke two RPC calls to object's `concatenate()` method. We create a method call message by invoking proxy's `createMethodCall()`. We serialize method input arguments into it, and make a synchronous call via proxy's `callMethod()`. As a return value we get the reply message as soon as it arrives. We deserialize return values from that message, and further use it in our program. The second `concatenate()` RPC call is done with invalid arguments, so we get a D-Bus error reply from the service, which as we can see is manifested via `sdbus::Error` exception being thrown. @@ -540,7 +540,7 @@ int main(int argc, char *argv[]) } ``` -> **_Tip_:** There's also an overload of `addVTable(...).forInterface()` method with `request_slot_t` tag parameter which returns a `Slot` object. The slot is a simple RAII-based handle of the associated vtable registration. As long as you keep the slot object, the vtable registration is active. When you let go of the slot, the vtable is automatically removed from the D-Bus object. This gives you the ability to implement "dynamic" D-Bus object API that is addable as well as removable at any time during object lifetime. +> **_Tip_:** There's also an overload of `addVTable(...).forInterface()` method with `return_slot_t` tag parameter which returns a `Slot` object. The slot is a simple RAII-based handle of the associated vtable registration. As long as you keep the slot object, the vtable registration is active. When you let go of the slot, the vtable is automatically removed from the D-Bus object. This gives you the ability to implement "dynamic" D-Bus object API that is addable as well as removable at any time during object lifetime. > **_Note_:** A D-Bus object can have any number of vtables attached to it. Even a D-Bus interface of an object can have multiple vtables attached to it. @@ -601,7 +601,7 @@ int main(int argc, char *argv[]) When registering methods, calling methods or emitting signals, multiple lines of code have shrunk into simple one-liners. Signatures of provided callbacks are introspected and types of provided arguments are deduced at compile time, so the D-Bus signatures as well as serialization and deserialization of arguments to and from D-Bus messages are generated for us completely by the compiler. -> **_Tip_:** There's also an overload of `uponSignal(...).call()` with `request_slot_t` tag which returns a `Slot` object. The slot is a simple RAII-based handle of the subscription. As long as you keep the slot object, the signal subscription is active. When you let go of the object, the signal handler is automatically unregistered. This gives you finer control over the lifetime of signal subscription. +> **_Tip_:** There's also an overload of `uponSignal(...).call()` with `return_slot_t` tag which returns a `Slot` object. The slot is a simple RAII-based handle of the subscription. As long as you keep the slot object, the signal subscription is active. When you let go of the object, the signal handler is automatically unregistered. This gives you finer control over the lifetime of signal subscription. We recommend that sdbus-c++ users prefer the convenience API to the lower level, basic API. When feasible, using generated adaptor and proxy C++ bindings is even better as it provides yet slightly higher abstraction built on top of the convenience API, where remote calls look simply like local, native calls of object methods. They are described in the following section. diff --git a/include/sdbus-c++/ConvenienceApiClasses.h b/include/sdbus-c++/ConvenienceApiClasses.h index f0c5db5..edaab71 100644 --- a/include/sdbus-c++/ConvenienceApiClasses.h +++ b/include/sdbus-c++/ConvenienceApiClasses.h @@ -53,7 +53,7 @@ namespace sdbus { public: VTableAdder(IObject& object, std::vector vtable); void forInterface(std::string interfaceName); - [[nodiscard]] Slot forInterface(std::string interfaceName, request_slot_t); + [[nodiscard]] Slot forInterface(std::string interfaceName, return_slot_t); private: IObject& object_; @@ -129,7 +129,7 @@ namespace sdbus { SignalSubscriber(IProxy& proxy, const std::string& signalName); SignalSubscriber& onInterface(std::string interfaceName); template void call(_Function&& callback); - template [[nodiscard]] Slot call(_Function&& callback, request_slot_t); + template [[nodiscard]] Slot call(_Function&& callback, return_slot_t); private: template signal_handler makeSignalHandler(_Function&& callback); diff --git a/include/sdbus-c++/ConvenienceApiClasses.inl b/include/sdbus-c++/ConvenienceApiClasses.inl index 178b277..b1dc8c2 100644 --- a/include/sdbus-c++/ConvenienceApiClasses.inl +++ b/include/sdbus-c++/ConvenienceApiClasses.inl @@ -57,9 +57,9 @@ namespace sdbus { object_.addVTable(std::move(interfaceName), std::move(vtable_)); } - inline Slot VTableAdder::forInterface(std::string interfaceName, request_slot_t) + inline Slot VTableAdder::forInterface(std::string interfaceName, return_slot_t) { - return object_.addVTable(std::move(interfaceName), std::move(vtable_), request_slot); + return object_.addVTable(std::move(interfaceName), std::move(vtable_), return_slot); } /*** ------------- ***/ @@ -311,14 +311,14 @@ namespace sdbus { } template - inline Slot SignalSubscriber::call(_Function&& callback, request_slot_t) + inline Slot SignalSubscriber::call(_Function&& callback, return_slot_t) { assert(!interfaceName_.empty()); // onInterface() must be placed/called prior to this function return proxy_.registerSignalHandler( interfaceName_ , signalName_ , makeSignalHandler(std::forward<_Function>(callback)) - , request_slot ); + , return_slot ); } template diff --git a/include/sdbus-c++/IObject.h b/include/sdbus-c++/IObject.h index a6fb9a5..187b35a 100644 --- a/include/sdbus-c++/IObject.h +++ b/include/sdbus-c++/IObject.h @@ -140,7 +140,7 @@ namespace sdbus { * * @throws sdbus::Error in case of failure */ - virtual Slot addVTable(std::string interfaceName, std::vector vtable, request_slot_t) = 0; + virtual Slot addVTable(std::string interfaceName, std::vector vtable, return_slot_t) = 0; /*! * @brief A little more convenient overload of addVTable() above diff --git a/include/sdbus-c++/IProxy.h b/include/sdbus-c++/IProxy.h index c3a2200..90a8ed0 100644 --- a/include/sdbus-c++/IProxy.h +++ b/include/sdbus-c++/IProxy.h @@ -224,7 +224,7 @@ namespace sdbus { [[nodiscard]] virtual Slot registerSignalHandler( const std::string& interfaceName , const std::string& signalName , signal_handler signalHandler - , request_slot_t ) = 0; + , return_slot_t ) = 0; /*! * @brief Unregisters proxy's signal handlers and stops receiving replies to pending async calls diff --git a/include/sdbus-c++/TypeTraits.h b/include/sdbus-c++/TypeTraits.h index a0b8825..0c6e6de 100644 --- a/include/sdbus-c++/TypeTraits.h +++ b/include/sdbus-c++/TypeTraits.h @@ -73,9 +73,9 @@ namespace sdbus { // Type-erased RAII-style handle to callbacks/subscriptions registered to sdbus-c++ using Slot = std::unique_ptr>; - // Tag specifying that an owning slot handle shall be returned from the function - struct request_slot_t { explicit request_slot_t() = default; }; - inline constexpr request_slot_t request_slot{}; + // 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{}; // Tag specifying that the library shall own the slot resulting from the call of the function (so-called floating slot) struct floating_slot_t { explicit floating_slot_t() = default; }; inline constexpr floating_slot_t floating_slot{}; diff --git a/src/Connection.cpp b/src/Connection.cpp index 539dfbf..bc9b371 100644 --- a/src/Connection.cpp +++ b/src/Connection.cpp @@ -198,7 +198,7 @@ void Connection::addObjectManager(const std::string& objectPath, floating_slot_t SDBUS_THROW_ERROR_IF(r < 0, "Failed to add object manager", -r); } -Slot Connection::addObjectManager(const std::string& objectPath, request_slot_t) +Slot Connection::addObjectManager(const std::string& objectPath, return_slot_t) { sd_bus_slot *slot{}; diff --git a/src/Connection.h b/src/Connection.h index 5c0f001..323028e 100644 --- a/src/Connection.h +++ b/src/Connection.h @@ -90,7 +90,7 @@ namespace sdbus::internal { void addObjectManager(const std::string& objectPath) override; void addObjectManager(const std::string& objectPath, floating_slot_t) override; - Slot addObjectManager(const std::string& objectPath, request_slot_t) override; + Slot addObjectManager(const std::string& objectPath, return_slot_t) override; void setMethodCallTimeout(uint64_t timeout) override; uint64_t getMethodCallTimeout() const override; diff --git a/src/IConnection.h b/src/IConnection.h index a1227c2..5145f3c 100644 --- a/src/IConnection.h +++ b/src/IConnection.h @@ -86,7 +86,7 @@ namespace sdbus::internal { , const std::vector& interfaces ) = 0; using sdbus::IConnection::addObjectManager; - [[nodiscard]] virtual Slot addObjectManager(const std::string& objectPath, request_slot_t) = 0; + [[nodiscard]] virtual Slot addObjectManager(const std::string& objectPath, return_slot_t) = 0; [[nodiscard]] virtual Slot registerSignalHandler( const std::string& sender , const std::string& objectPath diff --git a/src/Object.cpp b/src/Object.cpp index 51caa83..0634272 100644 --- a/src/Object.cpp +++ b/src/Object.cpp @@ -49,12 +49,12 @@ Object::Object(sdbus::internal::IConnection& connection, std::string objectPath) void Object::addVTable(std::string interfaceName, std::vector vtable) { - auto slot = Object::addVTable(std::move(interfaceName), std::move(vtable), request_slot); + auto slot = Object::addVTable(std::move(interfaceName), std::move(vtable), return_slot); vtables_.push_back(std::move(slot)); } -Slot Object::addVTable(std::string interfaceName, std::vector vtable, request_slot_t) +Slot Object::addVTable(std::string interfaceName, std::vector vtable, return_slot_t) { SDBUS_CHECK_INTERFACE_NAME(interfaceName); @@ -121,7 +121,7 @@ void Object::emitInterfacesRemovedSignal(const std::vector& interfa void Object::addObjectManager() { - objectManagerSlot_ = connection_.addObjectManager(objectPath_, request_slot); + objectManagerSlot_ = connection_.addObjectManager(objectPath_, return_slot); } void Object::removeObjectManager() diff --git a/src/Object.h b/src/Object.h index b7c6feb..91dea67 100644 --- a/src/Object.h +++ b/src/Object.h @@ -46,7 +46,7 @@ namespace sdbus::internal { Object(sdbus::internal::IConnection& connection, std::string objectPath); void addVTable(std::string interfaceName, std::vector vtable) override; - Slot addVTable(std::string interfaceName, std::vector vtable, request_slot_t) override; + Slot addVTable(std::string interfaceName, std::vector vtable, return_slot_t) override; void unregister() override; sdbus::Signal createSignal(const std::string& interfaceName, const std::string& signalName) override; diff --git a/src/Proxy.cpp b/src/Proxy.cpp index 390f3dd..004888f 100644 --- a/src/Proxy.cpp +++ b/src/Proxy.cpp @@ -136,7 +136,7 @@ void Proxy::registerSignalHandler( const std::string& interfaceName , const std::string& signalName , signal_handler signalHandler ) { - auto slot = Proxy::registerSignalHandler(interfaceName, signalName, std::move(signalHandler), request_slot); + auto slot = Proxy::registerSignalHandler(interfaceName, signalName, std::move(signalHandler), return_slot); floatingSignalSlots_.push_back(std::move(slot)); } @@ -144,7 +144,7 @@ void Proxy::registerSignalHandler( const std::string& interfaceName Slot Proxy::registerSignalHandler( const std::string& interfaceName , const std::string& signalName , signal_handler signalHandler - , request_slot_t ) + , return_slot_t ) { SDBUS_CHECK_INTERFACE_NAME(interfaceName); SDBUS_CHECK_MEMBER_NAME(signalName); diff --git a/src/Proxy.h b/src/Proxy.h index 7ae4abe..d47e4fd 100644 --- a/src/Proxy.h +++ b/src/Proxy.h @@ -65,7 +65,7 @@ namespace sdbus::internal { Slot registerSignalHandler( const std::string& interfaceName , const std::string& signalName , signal_handler signalHandler - , request_slot_t ) override; + , return_slot_t ) override; void unregister() override; sdbus::IConnection& getConnection() const override; diff --git a/tests/integrationtests/DBusMethodsTests.cpp b/tests/integrationtests/DBusMethodsTests.cpp index c052caf..b18b5f0 100644 --- a/tests/integrationtests/DBusMethodsTests.cpp +++ b/tests/integrationtests/DBusMethodsTests.cpp @@ -293,8 +293,8 @@ TYPED_TEST(SdbusTestObject, CanRegisterAdditionalVTableDynamicallyAtAnyTime) auto& object = this->m_adaptor->getObject(); auto vtableSlot = object.addVTable( "org.sdbuscpp.integrationtests2" , { sdbus::registerMethod("add").implementedAs([](const int64_t& a, const double& b){ return a + b; }) - , sdbus::registerMethod("subtract").implementedAs([](const int& a, const int& b){ return a - b; })} - , sdbus::request_slot ); + , sdbus::registerMethod("subtract").implementedAs([](const int& a, const int& b){ return a - b; }) } + , sdbus::return_slot ); // The new remote vtable is registered as long as we keep vtableSlot, so remote method calls now should pass auto proxy = sdbus::createProxy(BUS_NAME, OBJECT_PATH, sdbus::dont_run_event_loop_thread); @@ -310,8 +310,8 @@ TYPED_TEST(SdbusTestObject, CanUnregisterAdditionallyRegisteredVTableAtAnyTime) auto vtableSlot = object.addVTable( "org.sdbuscpp.integrationtests2" , { sdbus::registerMethod("add").implementedAs([](const int64_t& a, const double& b){ return a + b; }) - , sdbus::registerMethod("subtract").implementedAs([](const int& a, const int& b){ return a - b; })} - , sdbus::request_slot ); + , sdbus::registerMethod("subtract").implementedAs([](const int& a, const int& b){ return a - b; }) } + , sdbus::return_slot ); vtableSlot.reset(); // Letting the slot go means letting go the associated vtable registration // No such remote D-Bus method under given interface exists anymore... diff --git a/tests/integrationtests/integrationtests-proxy.h b/tests/integrationtests/integrationtests-proxy.h index c1ed8f2..1c86d92 100644 --- a/tests/integrationtests/integrationtests-proxy.h +++ b/tests/integrationtests/integrationtests-proxy.h @@ -33,7 +33,7 @@ protected: void registerProxy() { - simpleSignalSlot_ = proxy_->uponSignal("simpleSignal").onInterface(INTERFACE_NAME).call([this](){ this->onSimpleSignal(); }, sdbus::request_slot); + simpleSignalSlot_ = proxy_->uponSignal("simpleSignal").onInterface(INTERFACE_NAME).call([this](){ this->onSimpleSignal(); }, sdbus::return_slot); proxy_->uponSignal("signalWithMap").onInterface(INTERFACE_NAME).call([this](const std::map& aMap){ this->onSignalWithMap(aMap); }); proxy_->uponSignal("signalWithVariant").onInterface(INTERFACE_NAME).call([this](const sdbus::Variant& aVariant){ this->onSignalWithVariant(aVariant); }); } @@ -192,7 +192,7 @@ public: void reRegisterSimpleSignalHandler() { - simpleSignalSlot_ = proxy_->uponSignal("simpleSignal").onInterface(INTERFACE_NAME).call([this](){ this->onSimpleSignal(); }, sdbus::request_slot); + simpleSignalSlot_ = proxy_->uponSignal("simpleSignal").onInterface(INTERFACE_NAME).call([this](){ this->onSimpleSignal(); }, sdbus::return_slot); } public: