Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .clang-format
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# TODO: Introduce common clang-format rule set
DisableFormat: true
SortIncludes: false
16 changes: 8 additions & 8 deletions include/sdbus-c++/ConvenienceApiClasses.inl
Original file line number Diff line number Diff line change
Expand Up @@ -304,7 +304,7 @@ namespace sdbus {
template <typename Function>
inline async_reply_handler AsyncMethodInvoker::makeAsyncReplyHandler(Function&& callback)
{
return [callback = std::forward<Function>(callback)](MethodReply reply, std::optional<Error> error)
return [callback = std::forward<Function>(callback)](MethodReply reply, std::optional<Error> error) mutable
{
// Create a tuple of callback input arguments' types, which will be used
// as a storage for the argument values deserialized from the message.
Expand Down Expand Up @@ -334,18 +334,18 @@ namespace sdbus {
template <typename... Args>
std::future<future_return_t<Args...>> AsyncMethodInvoker::getResultAsFuture()
{
auto promise = std::make_shared<std::promise<future_return_t<Args...>>>();
auto future = promise->get_future();
std::promise<future_return_t<Args...>> promise{};
auto future = promise.get_future();

uponReplyInvoke([promise = std::move(promise)](std::optional<Error> error, Args... args)
uponReplyInvoke([promise = std::move(promise)](std::optional<Error> error, Args... args) mutable
{
if (!error)
if constexpr (!std::is_void_v<future_return_t<Args...>>)
promise->set_value({std::move(args)...});
promise.set_value({std::move(args)...});
else
promise->set_value();
promise.set_value();
else
promise->set_exception(std::make_exception_ptr(*std::move(error)));
promise.set_exception(std::make_exception_ptr(*std::move(error)));
});

// Will be std::future<void> for no D-Bus method return value
Expand Down Expand Up @@ -436,7 +436,7 @@ namespace sdbus {
template <typename Function>
inline signal_handler SignalSubscriber::makeSignalHandler(Function&& callback)
{
return [callback = std::forward<Function>(callback)](Signal signal)
return [callback = std::forward<Function>(callback)](Signal signal) mutable
{
// Create a tuple of callback input arguments' types, which will be used
// as a storage for the argument values deserialized from the signal message.
Expand Down
14 changes: 7 additions & 7 deletions include/sdbus-c++/IConnection.h
Original file line number Diff line number Diff line change
Expand Up @@ -277,7 +277,7 @@ namespace sdbus {
*
* @throws sdbus::Error in case of failure
*/
virtual void addMatch(const std::string& match, message_handler callback) = 0;
virtual void addMatch(const std::string& match, message_handler&& callback) = 0;

/*!
* @brief Installs a match rule for messages received on this bus connection
Expand All @@ -300,14 +300,14 @@ namespace sdbus {
*
* @throws sdbus::Error in case of failure
*/
[[nodiscard]] virtual Slot addMatch(const std::string& match, message_handler callback, return_slot_t) = 0;
[[nodiscard]] virtual Slot addMatch(const std::string& match, message_handler&& callback, return_slot_t) = 0;

/*!
* @brief Asynchronously installs a floating match rule for messages received on this bus connection
*
* @param[in] match Match expression to filter incoming D-Bus message
* @param[in] callback Callback handler to be called upon processing an inbound D-Bus message matching the rule
* @param[in] installCallback Callback handler to be called upon processing an inbound D-Bus message matching the rule
* @param[in] installCallback One-shot handler invoked once with the broker's response to the install request
*
* This method operates the same as `addMatch()` above, just that it installs the match rule asynchronously,
* in a non-blocking fashion. A request is sent to the broker, but the call does not wait for a response.
Expand All @@ -323,14 +323,14 @@ namespace sdbus {
*
* @throws sdbus::Error in case of failure
*/
virtual void addMatchAsync(const std::string& match, message_handler callback, message_handler installCallback) = 0;
virtual void addMatchAsync(const std::string& match, message_handler&& callback, match_install_handler&& installCallback) = 0;

/*!
* @brief Asynchronously installs a match rule for messages received on this bus connection
*
* @param[in] match Match expression to filter incoming D-Bus message
* @param[in] callback Callback handler to be called upon processing an inbound D-Bus message matching the rule
* @param[in] installCallback Callback handler to be called upon processing an inbound D-Bus message matching the rule
* @param[in] installCallback One-shot handler invoked once with the broker's response to the install request
* @return RAII-style slot handle representing the ownership of the subscription
*
* This method operates the same as `addMatch()` above, just that it installs the match rule asynchronously,
Expand All @@ -347,8 +347,8 @@ namespace sdbus {
* @throws sdbus::Error in case of failure
*/
[[nodiscard]] virtual Slot addMatchAsync( const std::string& match
, message_handler callback
, message_handler installCallback
, message_handler&& callback
, match_install_handler&& installCallback
, return_slot_t ) = 0;

/*!
Expand Down
14 changes: 12 additions & 2 deletions include/sdbus-c++/IObject.h
Original file line number Diff line number Diff line change
Expand Up @@ -442,13 +442,23 @@ namespace sdbus {
template <typename... VTableItems, typename>
void IObject::addVTable(InterfaceName interfaceName, VTableItems&&... items)
{
addVTable(std::move(interfaceName), {std::forward<VTableItems>(items)...});
// Built via emplace_back rather than a braced initializer_list: items hold move-only
// callbacks, and initializer_list elements are const (copy-only).
std::vector<VTableItem> vtable;
vtable.reserve(sizeof...(items));
(vtable.emplace_back(std::forward<VTableItems>(items)), ...);
addVTable(std::move(interfaceName), std::move(vtable));
}

template <typename... VTableItems, typename>
VTableAdder IObject::addVTable(VTableItems&&... items)
{
return addVTable(std::vector<VTableItem>{std::forward<VTableItems>(items)...});
// Built via emplace_back rather than a braced initializer_list: items hold move-only
// callbacks, and initializer_list elements are const (copy-only).
std::vector<VTableItem> vtable;
vtable.reserve(sizeof...(items));
(vtable.emplace_back(std::forward<VTableItems>(items)), ...);
return addVTable(std::move(vtable));
}

inline VTableAdder IObject::addVTable(std::vector<VTableItem> vtable)
Expand Down
24 changes: 12 additions & 12 deletions include/sdbus-c++/IProxy.h
Original file line number Diff line number Diff line change
Expand Up @@ -455,7 +455,7 @@ namespace sdbus {
*
* @throws sdbus::Error in case of failure
*/
virtual PendingAsyncCall callMethodAsync(const MethodCall& message, async_reply_handler asyncReplyCallback) = 0;
virtual PendingAsyncCall callMethodAsync(const MethodCall& message, async_reply_handler&& asyncReplyCallback) = 0;

/*!
* @brief Calls method on the D-Bus object asynchronously
Expand All @@ -480,7 +480,7 @@ namespace sdbus {
* @throws sdbus::Error in case of failure
*/
[[nodiscard]] virtual Slot callMethodAsync( const MethodCall& message
, async_reply_handler asyncReplyCallback
, async_reply_handler&& asyncReplyCallback
, return_slot_t ) = 0;

/*!
Expand All @@ -506,7 +506,7 @@ namespace sdbus {
* @throws sdbus::Error in case of failure
*/
virtual PendingAsyncCall callMethodAsync( const MethodCall& message
, async_reply_handler asyncReplyCallback
, async_reply_handler&& asyncReplyCallback
, uint64_t timeout ) = 0;

/*!
Expand All @@ -533,7 +533,7 @@ namespace sdbus {
* @throws sdbus::Error in case of failure
*/
[[nodiscard]] virtual Slot callMethodAsync( const MethodCall& message
, async_reply_handler asyncReplyCallback
, async_reply_handler&& asyncReplyCallback
, uint64_t timeout
, return_slot_t ) = 0;

Expand All @@ -542,15 +542,15 @@ namespace sdbus {
*/
template <typename Rep, typename Period>
PendingAsyncCall callMethodAsync( const MethodCall& message
, async_reply_handler asyncReplyCallback
, async_reply_handler&& asyncReplyCallback
, const std::chrono::duration<Rep, Period>& timeout );

/*!
* @copydoc IProxy::callMethod(const MethodCall&,async_reply_handler,uint64_t,return_slot_t)
*/
template <typename Rep, typename Period>
[[nodiscard]] Slot callMethodAsync( const MethodCall& message
, async_reply_handler asyncReplyCallback
, async_reply_handler&& asyncReplyCallback
, const std::chrono::duration<Rep, Period>& timeout
, return_slot_t );

Expand Down Expand Up @@ -669,7 +669,7 @@ namespace sdbus {
*/
virtual void registerSignalHandler( const InterfaceName& interfaceName
, const SignalName& signalName
, signal_handler signalHandler ) = 0;
, signal_handler&& signalHandler ) = 0;

/*!
* @brief Registers a handler for the desired signal emitted by the D-Bus object
Expand All @@ -689,7 +689,7 @@ namespace sdbus {
*/
[[nodiscard]] virtual Slot registerSignalHandler( const InterfaceName& interfaceName
, const SignalName& signalName
, signal_handler signalHandler
, signal_handler&& signalHandler
, return_slot_t ) = 0;

protected: // Internal API for efficiency reasons used by high-level API helper classes
Expand All @@ -700,10 +700,10 @@ namespace sdbus {
[[nodiscard]] virtual MethodCall createMethodCall(const char* interfaceName, const char* methodName) const = 0;
virtual void registerSignalHandler( const char* interfaceName
, const char* signalName
, signal_handler signalHandler ) = 0;
, signal_handler&& signalHandler ) = 0;
[[nodiscard]] virtual Slot registerSignalHandler( const char* interfaceName
, const char* signalName
, signal_handler signalHandler
, signal_handler&& signalHandler
, return_slot_t ) = 0;
};

Expand Down Expand Up @@ -759,7 +759,7 @@ namespace sdbus {

template <typename Rep, typename Period>
inline PendingAsyncCall IProxy::callMethodAsync( const MethodCall& message
, async_reply_handler asyncReplyCallback
, async_reply_handler&& asyncReplyCallback
, const std::chrono::duration<Rep, Period>& timeout )
{
auto microsecs = std::chrono::duration_cast<std::chrono::microseconds>(timeout);
Expand All @@ -768,7 +768,7 @@ namespace sdbus {

template <typename Rep, typename Period>
inline Slot IProxy::callMethodAsync( const MethodCall& message
, async_reply_handler asyncReplyCallback
, async_reply_handler&& asyncReplyCallback
, const std::chrono::duration<Rep, Period>& timeout
, return_slot_t )
{
Expand Down
27 changes: 20 additions & 7 deletions include/sdbus-c++/TypeTraits.h
Original file line number Diff line number Diff line change
Expand Up @@ -74,15 +74,21 @@ namespace sdbus {
namespace sdbus {

// Callbacks from sdbus-c++
using method_callback = std::function<void(MethodCall msg)>;
using async_reply_handler = std::function<void(MethodReply reply, std::optional<Error> error)>;
using signal_handler = std::function<void(Signal signal)>;
using message_handler = std::function<void(Message msg)>;
using property_set_callback = std::function<void(PropertySetCall msg)>;
using property_get_callback = std::function<void(PropertyGetReply& reply)>;
// Repeatable server-side and client-side callbacks
using method_callback = std::move_only_function<void(MethodCall msg)>;
using property_set_callback = std::move_only_function<void(PropertySetCall msg)>;
using property_get_callback = std::move_only_function<void(PropertyGetReply& reply)>;
using signal_handler = std::move_only_function<void(Signal signal)>;
using message_handler = std::move_only_function<void(Message msg)>;

// One-shot callbacks: invoked exactly once (async reply arrives / match rule installed).
// Rvalue-qualified so the library must std::move to invoke, making the call-once contract
// visible at the call site and letting handlers move-consume captured resources.
using async_reply_handler = std::move_only_function<void(MethodReply reply, std::optional<Error> error) &&>;
using match_install_handler = std::move_only_function<void(Message msg) &&>;

// Type-erased RAII-style handle to callbacks/subscriptions registered to sdbus-c++
using Slot = std::unique_ptr<void, std::function<void(void*)>>;
using Slot = std::unique_ptr<void, std::move_only_function<void(void*)>>;

// Tag specifying that an owning handle (so-called slot) of the logical resource shall be provided to the client
struct return_slot_t { explicit return_slot_t() = default; };
Expand Down Expand Up @@ -380,6 +386,9 @@ namespace sdbus {
static constexpr bool is_trivial_dbus_type = false;
};

template <typename... Types>
concept valid_signature = signature_of<Types...>::is_valid;

// To simplify conversions of arrays to C strings
template <typename T, std::size_t N>
constexpr auto as_null_terminated(std::array<T, N> arr)
Expand Down Expand Up @@ -508,6 +517,10 @@ namespace sdbus {
struct function_traits<std::function<FunctionType>> : function_traits<FunctionType>
{};

template <typename FunctionType>
struct function_traits<std::move_only_function<FunctionType>> : function_traits<FunctionType>
{};

template <class Function>
constexpr auto is_async_method_v = function_traits<Function>::is_async;

Expand Down
42 changes: 21 additions & 21 deletions include/sdbus-c++/VTableItems.h
Original file line number Diff line number Diff line change
Expand Up @@ -38,14 +38,14 @@ namespace sdbus {

struct MethodVTableItem
{
template <typename Function> MethodVTableItem& implementedAs(Function&& callback);
MethodVTableItem& withInputParamNames(std::vector<std::string> names);
template <typename... String> MethodVTableItem& withInputParamNames(String... names);
MethodVTableItem& withOutputParamNames(std::vector<std::string> names);
template <typename... String> MethodVTableItem& withOutputParamNames(String... names);
MethodVTableItem& markAsDeprecated();
MethodVTableItem& markAsPrivileged();
MethodVTableItem& withNoReply();
template <typename Function> MethodVTableItem&& implementedAs(Function&& callback) &&;
MethodVTableItem&& withInputParamNames(std::vector<std::string> names) &&;
template <typename... String> MethodVTableItem&& withInputParamNames(String... names) &&;
MethodVTableItem&& withOutputParamNames(std::vector<std::string> names) &&;
template <typename... String> MethodVTableItem&& withOutputParamNames(String... names) &&;
MethodVTableItem&& markAsDeprecated() &&;
MethodVTableItem&& markAsPrivileged() &&;
MethodVTableItem&& withNoReply() &&;

MethodName name;
Signature inputSignature;
Expand All @@ -61,10 +61,10 @@ namespace sdbus {

struct SignalVTableItem
{
template <typename... Args> SignalVTableItem& withParameters();
template <typename... Args> SignalVTableItem& withParameters(std::vector<std::string> names);
template <typename... Args, typename... String> SignalVTableItem& withParameters(String... names);
SignalVTableItem& markAsDeprecated();
template <typename... Args> SignalVTableItem&& withParameters() &&;
template <typename... Args> SignalVTableItem&& withParameters(std::vector<std::string> names) &&;
template <typename... Args, typename... String> SignalVTableItem&& withParameters(String... names) &&;
SignalVTableItem&& markAsDeprecated() &&;

SignalName name;
Signature signature;
Expand All @@ -77,11 +77,11 @@ namespace sdbus {

struct PropertyVTableItem
{
template <typename Function> PropertyVTableItem& withGetter(Function&& callback);
template <typename Function> PropertyVTableItem& withSetter(Function&& callback);
PropertyVTableItem& markAsDeprecated();
PropertyVTableItem& markAsPrivileged();
PropertyVTableItem& withUpdateBehavior(Flags::PropertyUpdateBehaviorFlags behavior);
template <typename Function> PropertyVTableItem&& withGetter(Function&& callback) &&;
template <typename Function> PropertyVTableItem&& withSetter(Function&& callback) &&;
PropertyVTableItem&& markAsDeprecated() &&;
PropertyVTableItem&& markAsPrivileged() &&;
PropertyVTableItem&& withUpdateBehavior(Flags::PropertyUpdateBehaviorFlags behavior) &&;

PropertyName name;
Signature signature;
Expand All @@ -95,10 +95,10 @@ namespace sdbus {

struct InterfaceFlagsVTableItem
{
InterfaceFlagsVTableItem& markAsDeprecated();
InterfaceFlagsVTableItem& markAsPrivileged();
InterfaceFlagsVTableItem& withNoReplyMethods();
InterfaceFlagsVTableItem& withPropertyUpdateBehavior(Flags::PropertyUpdateBehaviorFlags behavior);
InterfaceFlagsVTableItem&& markAsDeprecated() &&;
InterfaceFlagsVTableItem&& markAsPrivileged() &&;
InterfaceFlagsVTableItem&& withNoReplyMethods() &&;
InterfaceFlagsVTableItem&& withPropertyUpdateBehavior(Flags::PropertyUpdateBehaviorFlags behavior) &&;

Flags flags;
};
Expand Down
Loading
Loading