├── .clang-format ├── .flake8 ├── .gitignore ├── .isort.cfg ├── .markdownlint.yaml ├── .prettierrc.yaml ├── .shellcheck ├── .shellcheckrc ├── LICENSE ├── OWNERS ├── README.md ├── docs ├── asio.md └── yaml │ ├── error.md │ └── interface.md ├── example ├── asio-example.cpp ├── calculator-aserver.cpp ├── calculator-client.cpp ├── calculator-server.cpp ├── coroutine-example.cpp ├── gen │ ├── meson.build │ ├── net │ │ ├── meson.build │ │ └── poettering │ │ │ ├── Calculator │ │ │ └── meson.build │ │ │ └── meson.build │ ├── regenerate-meson │ └── run-ci ├── get-all-properties.cpp ├── list-users.cpp ├── meson.build ├── register-property.cpp └── yaml │ └── net │ └── poettering │ ├── Calculator.events.yaml │ └── Calculator.interface.yaml ├── include └── sdbusplus │ ├── asio │ ├── connection.hpp │ ├── detail │ │ └── async_send_handler.hpp │ ├── object_server.hpp │ ├── property.hpp │ └── sd_event.hpp │ ├── async.hpp │ ├── async │ ├── callback.hpp │ ├── client.hpp │ ├── context.hpp │ ├── execution.hpp │ ├── fdio.hpp │ ├── match.hpp │ ├── mutex.hpp │ ├── proxy.hpp │ ├── server.hpp │ ├── stdexec │ │ ├── __detail │ │ │ ├── __as_awaitable.hpp │ │ │ ├── __awaitable.hpp │ │ │ ├── __basic_sender.hpp │ │ │ ├── __bulk.hpp │ │ │ ├── __completion_signatures.hpp │ │ │ ├── __concepts.hpp │ │ │ ├── __config.hpp │ │ │ ├── __connect_awaitable.hpp │ │ │ ├── __continue_on.hpp │ │ │ ├── __continues_on.hpp │ │ │ ├── __cpo.hpp │ │ │ ├── __debug.hpp │ │ │ ├── __diagnostics.hpp │ │ │ ├── __domain.hpp │ │ │ ├── __ensure_started.hpp │ │ │ ├── __env.hpp │ │ │ ├── __execute.hpp │ │ │ ├── __execution_fwd.hpp │ │ │ ├── __force_include.hpp │ │ │ ├── __inline_scheduler.hpp │ │ │ ├── __into_variant.hpp │ │ │ ├── __intrusive_mpsc_queue.hpp │ │ │ ├── __intrusive_ptr.hpp │ │ │ ├── __intrusive_queue.hpp │ │ │ ├── __intrusive_slist.hpp │ │ │ ├── __just.hpp │ │ │ ├── __let.hpp │ │ │ ├── __manual_lifetime.hpp │ │ │ ├── __meta.hpp │ │ │ ├── __on.hpp │ │ │ ├── __operation_states.hpp │ │ │ ├── __optional.hpp │ │ │ ├── __p2300.hpp │ │ │ ├── __ranges.hpp │ │ │ ├── __read_env.hpp │ │ │ ├── __receiver_adaptor.hpp │ │ │ ├── __receiver_ref.hpp │ │ │ ├── __receivers.hpp │ │ │ ├── __run_loop.hpp │ │ │ ├── __schedule_from.hpp │ │ │ ├── __schedulers.hpp │ │ │ ├── __scope.hpp │ │ │ ├── __sender_adaptor_closure.hpp │ │ │ ├── __sender_introspection.hpp │ │ │ ├── __senders.hpp │ │ │ ├── __senders_core.hpp │ │ │ ├── __shared.hpp │ │ │ ├── __spin_loop_pause.hpp │ │ │ ├── __split.hpp │ │ │ ├── __start_detached.hpp │ │ │ ├── __start_on.hpp │ │ │ ├── __starts_on.hpp │ │ │ ├── __stop_token.hpp │ │ │ ├── __stopped_as_error.hpp │ │ │ ├── __stopped_as_optional.hpp │ │ │ ├── __submit.hpp │ │ │ ├── __sync_wait.hpp │ │ │ ├── __tag_invoke.hpp │ │ │ ├── __then.hpp │ │ │ ├── __transfer_just.hpp │ │ │ ├── __transform_completion_signatures.hpp │ │ │ ├── __transform_sender.hpp │ │ │ ├── __tuple.hpp │ │ │ ├── __type_traits.hpp │ │ │ ├── __upon_error.hpp │ │ │ ├── __upon_stopped.hpp │ │ │ ├── __utility.hpp │ │ │ ├── __variant.hpp │ │ │ ├── __when_all.hpp │ │ │ ├── __with_awaitable_senders.hpp │ │ │ └── __write_env.hpp │ │ ├── any_sender_of.hpp │ │ ├── async_scope.hpp │ │ ├── at_coroutine_exit.hpp │ │ ├── commit.info │ │ ├── concepts.hpp │ │ ├── coroutine.hpp │ │ ├── env.hpp │ │ ├── execution.hpp │ │ ├── functional.hpp │ │ ├── import │ │ ├── inline_scheduler.hpp │ │ ├── scope.hpp │ │ ├── sequence_senders.hpp │ │ ├── stop_token.hpp │ │ └── task.hpp │ ├── task.hpp │ └── timer.hpp │ ├── bus.hpp │ ├── bus │ └── match.hpp │ ├── event.hpp │ ├── exception.hpp │ ├── message.hpp │ ├── message │ ├── append.hpp │ ├── native_types.hpp │ ├── read.hpp │ └── types.hpp │ ├── sdbus.hpp │ ├── sdbuspp_support │ ├── event.hpp │ └── server.hpp │ ├── server.hpp │ ├── server │ ├── README.md │ ├── interface.hpp │ ├── manager.hpp │ ├── object.hpp │ └── transaction.hpp │ ├── slot.hpp │ ├── test │ └── sdbus_mock.hpp │ ├── timer.hpp │ ├── unpack_properties.hpp │ ├── utility │ ├── consteval_string.hpp │ ├── container_traits.hpp │ ├── dedup_variant.hpp │ ├── make_dbus_args_tuple.hpp │ ├── memory.hpp │ ├── merge_variants.hpp │ ├── tuple_to_array.hpp │ └── type_traits.hpp │ └── vtable.hpp ├── meson.build ├── meson.options ├── pyproject.toml ├── setup.cfg ├── src ├── async │ ├── context.cpp │ ├── fdio.cpp │ ├── match.cpp │ └── mutex.cpp ├── bus.cpp ├── bus │ └── match.cpp ├── event.cpp ├── exception.cpp ├── message │ └── native_types.cpp ├── sdbus.cpp └── server │ ├── interface.cpp │ └── transaction.cpp ├── subprojects ├── googletest.wrap └── nlohmann_json.wrap ├── test ├── async │ ├── context.cpp │ ├── fdio.cpp │ ├── fdio_timed.cpp │ ├── mutex.cpp │ ├── task.cpp │ ├── timer.cpp │ └── watchdog.cpp ├── bus │ ├── aio.cpp │ ├── exception.cpp │ ├── list_names.cpp │ └── match.cpp ├── event │ └── event.cpp ├── exception │ └── sdbus_error.cpp ├── gen │ ├── meson.build │ ├── regenerate-meson │ ├── run-ci │ ├── server │ │ ├── Test │ │ │ └── meson.build │ │ ├── Test2 │ │ │ └── meson.build │ │ ├── Test3 │ │ │ └── meson.build │ │ ├── TestWithMethod │ │ │ └── meson.build │ │ └── meson.build │ ├── test_aserver_emit_interfaces_added_signal.cpp │ ├── test_aserver_multiple_interfaces.cpp │ ├── test_aserver_no_uninitialized_value_constructor.cpp │ ├── test_method_names.cpp │ ├── test_property_names.cpp │ ├── test_server_no_uninitialized_value_constructor.cpp │ └── test_signal_names.cpp ├── meson.build ├── message │ ├── append.cpp │ ├── call.cpp │ ├── native_types.cpp │ ├── read.cpp │ └── types.cpp ├── server │ ├── message_variant.cpp │ └── object.cpp ├── timer.cpp ├── unpack_properties.cpp ├── utility │ ├── make_dbus_args_tuple.cpp │ ├── tuple_to_array.cpp │ └── type_traits.cpp ├── valgrind.supp ├── vtable │ ├── vtable.cpp │ └── vtable_c.c └── yaml │ └── server │ ├── Test.interface.yaml │ ├── Test2.interface.yaml │ ├── Test3.interface.yaml │ └── TestWithMethod.interface.yaml └── tools ├── README.md ├── meson.build ├── pyproject.toml ├── sdbus++ ├── sdbus++-gen-meson └── sdbusplus ├── __init__.py ├── enum.py ├── error.py ├── event.py ├── interface.py ├── main.py ├── method.py ├── namedelement.py ├── path.py ├── property.py ├── renderer.py ├── schemas └── events.schema.yaml ├── servicename.py ├── signal.py └── templates ├── error.cpp.mako ├── error.hpp.mako ├── error.md.mako ├── event.cpp.mako ├── event.hpp.mako ├── event.md.mako ├── events.cpp.mako ├── events.hpp.mako ├── events.md.mako ├── interface.aserver.hpp.mako ├── interface.client.hpp.mako ├── interface.common.hpp.mako ├── interface.md.mako ├── interface.server.cpp.mako ├── interface.server.hpp.mako ├── method.aserver.callback.hpp.mako ├── method.aserver.tag.hpp.mako ├── method.aserver.typeid.hpp.mako ├── method.aserver.vtable.hpp.mako ├── method.client.hpp.mako ├── method.md.mako ├── method.prototype.hpp.mako ├── method.server.vtable.cpp.mako ├── property.aserver.callback.hpp.mako ├── property.aserver.get.hpp.mako ├── property.aserver.set.hpp.mako ├── property.aserver.tag.hpp.mako ├── property.aserver.typeid.hpp.mako ├── property.aserver.vtable.hpp.mako ├── property.client.hpp.mako ├── property.md.mako ├── property.server.cpp.mako ├── property.server.vtable.cpp.mako ├── signal.aserver.emit.hpp.mako ├── signal.aserver.typeid.hpp.mako ├── signal.aserver.vtable.hpp.mako ├── signal.md.mako ├── signal.prototype.hpp.mako └── signal.server.vtable.cpp.mako /.flake8: -------------------------------------------------------------------------------- 1 | # Autoformatter friendly flake8 config (all formatting rules disabled) 2 | [flake8] 3 | extend-ignore = E1, E2, E3, E501, W1, W2, W3, W5 4 | -------------------------------------------------------------------------------- /.isort.cfg: -------------------------------------------------------------------------------- 1 | [settings] 2 | profile=black 3 | -------------------------------------------------------------------------------- /.markdownlint.yaml: -------------------------------------------------------------------------------- 1 | default: true 2 | MD024: 3 | siblings_only: true 4 | MD013: 5 | stern: true 6 | -------------------------------------------------------------------------------- /.prettierrc.yaml: -------------------------------------------------------------------------------- 1 | tabWidth: 4 2 | printWidth: 80 3 | proseWrap: "always" 4 | overrides: 5 | - files: "*.md" 6 | options: 7 | tabWidth: 2 8 | -------------------------------------------------------------------------------- /.shellcheck: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/openbmc/sdbusplus/c6fee5a94bbb4b4fbb6212942f0f2cfa3049c255/.shellcheck -------------------------------------------------------------------------------- /.shellcheckrc: -------------------------------------------------------------------------------- 1 | enable=all 2 | source-path=SCRIPTDIR 3 | disable=SC2154 4 | -------------------------------------------------------------------------------- /OWNERS: -------------------------------------------------------------------------------- 1 | # OWNERS 2 | # ------ 3 | # 4 | # The OWNERS file maintains the list of individuals responsible for various 5 | # parts of this repository, including code review and approval. We use the 6 | # Gerrit 'owners' plugin, which consumes this file, along with some extra 7 | # keywords for our own purposes and tooling. 8 | # 9 | # For details on the configuration used by 'owners' see: 10 | # https://gerrit.googlesource.com/plugins/owners/+/refs/heads/master/owners/src/main/resources/Documentation/config.md 11 | # 12 | # An OWNERS file must be in the root of a repository but may also be present 13 | # in any subdirectory. The contents of the subdirectory OWNERS file are 14 | # combined with parent directories unless 'inherit: false' is set. 15 | # 16 | # The owners file is YAML and has [up to] 4 top-level keywords. 17 | # * owners: A list of individuals who have approval authority on the 18 | # repository. 19 | # 20 | # * reviewers: A list of individuals who have requested review notification 21 | # on the repository. 22 | # 23 | # * matchers: A list of specific file/path matchers for granular 'owners' and 24 | # 'reviewers'. See 'owners' plugin documentation. 25 | # 26 | # * openbmc: A list of openbmc-specific meta-data about owners and reviewers. 27 | # - name: preferred name of the individual. 28 | # - email: preferred email address of the individual. 29 | # - discord: Discord nickname of the individual. 30 | # 31 | # It is expected that these 4 sections will be listed in the order above and 32 | # data within them will be kept sorted. 33 | 34 | owners: 35 | - patrick@stwcx.xyz 36 | - wak@google.com 37 | 38 | reviewers: 39 | - vernon.mauery@gmail.com 40 | - mine260309@gmail.com 41 | - ed@tanous.net 42 | 43 | matchers: 44 | 45 | openbmc: 46 | - name: Lei Yu 47 | email: mine260309@gmail.com 48 | discord: LeiYU 49 | - name: Patrick Williams 50 | email: patrick@stwcx.xyz 51 | discord: stwcx 52 | - name: Vernon Mauery 53 | email: vernon.mauery@gmail.com 54 | discord: vmauery 55 | - name: William Kennington 56 | email: wak@google.com 57 | discord: wak 58 | -------------------------------------------------------------------------------- /docs/asio.md: -------------------------------------------------------------------------------- 1 | # ASIO 2 | 3 | ## Properties 4 | 5 | Properties can be dynamically registered to an interface by calling 6 | `register_property()`. If you need to provide a custom getter or setter for a 7 | property, it should follow the guidelines in this section. 8 | 9 | To return a D-Bus error reply for either GetProperty or SetProperty, throw a 10 | custom exception derived from `sdbusplus::exception_t`. For the custom 11 | exception, you can return a well-defined [org.freedesktop.DBus.Error][1] from 12 | the `name()` or a custom/arbitrary name. The former will be automatically 13 | translated into a matching [error code][2] that can be consumed by the caller, 14 | while the latter will always be mapped to `EIO`, requiring a `strcmp` to 15 | determine the exact error name. 16 | 17 | The handler may also throw any exception not derived from 18 | `sdbusplus::exception_t`, in which case a generic 19 | org.freedesktop.DBus.Error.InvalidArgs error will be returned to the caller. 20 | 21 | [1]: https://www.freedesktop.org/software/systemd/man/sd-bus-errors.html# 22 | [2]: 23 | https://github.com/systemd/systemd/blob/485c9e19e7ebcd912d5fbf11f40afc62951173f8/src/libsystemd/sd-bus/bus-error.c 24 | 25 | ### Get Property callback 26 | 27 | When registering a property using ASIO methods, the get callback should meet the 28 | following prototype: 29 | 30 | ```c++ 31 | PropertyType getHandler(const PropertyType& value); 32 | ``` 33 | 34 | The first argument is the current value cached in the D-Bus interface (i.e. the 35 | previously "getted" value, or the initialized value), and the return value is 36 | returned to the D-Bus caller. 37 | 38 | ### Set Property callback 39 | 40 | When registering a writable property using ASIO methods, the set callback should 41 | meet the following prototype: 42 | 43 | ```c++ 44 | bool setHandler(const PropertyType& newValue, PropertyType& value); 45 | ``` 46 | 47 | The first argument is the new value requested to be set by the D-Bus caller. 48 | 49 | The second argument is the actual underlying value contained within the object 50 | server. If the new value meets the expected constraints, the handler must set 51 | `value = newValue` to make the set operation take effect and return true. If the 52 | new value is invalid or cannot be applied for whatever reason, the handler must 53 | leave `value` unmodified and return false. 54 | 55 | If the handler returns false but doesn't throw an exception, a generic 56 | org.freedesktop.DBus.Error.InvalidArgs error will be returned to the caller. 57 | -------------------------------------------------------------------------------- /docs/yaml/error.md: -------------------------------------------------------------------------------- 1 | # Error YAML 2 | 3 | D-Bus errors can be defined by creating a YAML file to describe the errors. From 4 | this YAML file, both documentation and binding code may be generated. The 5 | generated bindings are C++ exception types corresponding to the D-Bus error 6 | name. Ex. `org.freedesktop.Example.Error.SomeError` will create a generated 7 | exception type of `sdbusplus::error::org::freedesktop::example::SomeError` which 8 | may be thrown or caught as appropriate. If the error is thrown from an interface 9 | method which has specified it may return that error, then the bindings will 10 | generate a catch clause that returns a D-Bus error like 11 | "org.freedesktop.Example.Error.SomeError" to the method caller. 12 | 13 | The error YAML is simply a list of `name` along with optional `description` and 14 | `errno` properties. Example: 15 | 16 | ```yaml 17 | - name: SomeError 18 | - name: AnotherError 19 | description: > 20 | This is another error. 21 | errno: E2BIG 22 | ``` 23 | -------------------------------------------------------------------------------- /example/calculator-aserver.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include 5 | 6 | class Calculator : 7 | public sdbusplus::aserver::net::poettering::Calculator 8 | { 9 | public: 10 | explicit Calculator(sdbusplus::async::context& ctx, auto path) : 11 | sdbusplus::aserver::net::poettering::Calculator(ctx, path) 12 | {} 13 | 14 | auto method_call(multiply_t, auto x, auto y) 15 | { 16 | auto r = x * y; 17 | last_result(r); 18 | return r; 19 | } 20 | 21 | auto method_call(divide_t, auto x, auto y) 22 | -> sdbusplus::async::task 23 | { 24 | using sdbusplus::error::net::poettering::Calculator::DivisionByZero; 25 | if (y == 0) 26 | { 27 | status(State::Error); 28 | throw DivisionByZero(); 29 | } 30 | 31 | auto r = x / y; 32 | last_result(r); 33 | co_return r; 34 | } 35 | 36 | auto method_call(clear_t) -> sdbusplus::async::task<> 37 | { 38 | auto v = last_result(); 39 | last_result(0); 40 | cleared(v); 41 | co_return; 42 | } 43 | 44 | auto get_property(owner_t) const 45 | { 46 | std::cout << " get_property on owner\n"; 47 | return owner_; 48 | } 49 | 50 | bool set_property(owner_t, auto owner) 51 | { 52 | std::cout << " set_property on owner\n"; 53 | std::swap(owner_, owner); 54 | return owner_ == owner; 55 | } 56 | }; 57 | 58 | int main() 59 | { 60 | constexpr auto path = Calculator::instance_path; 61 | 62 | sdbusplus::async::context ctx; 63 | sdbusplus::server::manager_t manager{ctx, path}; 64 | 65 | Calculator c{ctx, path}; 66 | 67 | ctx.spawn([](sdbusplus::async::context& ctx) -> sdbusplus::async::task<> { 68 | ctx.request_name(Calculator::default_service); 69 | co_return; 70 | }(ctx)); 71 | 72 | ctx.run(); 73 | 74 | return 0; 75 | } 76 | -------------------------------------------------------------------------------- /example/calculator-client.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include 5 | 6 | auto startup(sdbusplus::async::context& ctx) -> sdbusplus::async::task<> 7 | { 8 | using Calculator = sdbusplus::client::net::poettering::Calculator<>; 9 | 10 | auto c = Calculator(ctx) 11 | .service(Calculator::default_service) 12 | .path(Calculator::instance_path); 13 | 14 | // Alternatively, sdbusplus::async::client_t() could have 15 | // been used to combine multiple interfaces into a single client-proxy. 16 | auto alternative_c [[maybe_unused]] = 17 | sdbusplus::async::client_t< 18 | sdbusplus::client::net::poettering::Calculator>(ctx) 19 | .service(Calculator::default_service) 20 | .path(Calculator::instance_path); 21 | 22 | { 23 | // Call the Multiply method. 24 | auto _ = co_await c.multiply(7, 6); 25 | std::cout << "Should be 42: " << _ << std::endl; 26 | } 27 | 28 | { 29 | // Get the LastResult property. 30 | auto _ = co_await c.last_result(); 31 | std::cout << "Should be 42: " << _ << std::endl; 32 | } 33 | 34 | { 35 | // Call the Clear method. 36 | co_await c.clear(); 37 | } 38 | 39 | { 40 | // Get the LastResult property. 41 | auto _ = co_await c.last_result(); 42 | std::cout << "Should be 0: " << _ << std::endl; 43 | } 44 | 45 | { 46 | // Set the LastResult property. 47 | co_await c.last_result(1234); 48 | // Get the LastResult property. 49 | auto _ = co_await c.last_result(); 50 | std::cout << "Should be 1234: " << _ << std::endl; 51 | } 52 | 53 | { 54 | co_await c.owner("client"); 55 | } 56 | 57 | { 58 | auto _ = co_await c.owner(); 59 | std::cout << "Should be 'client': " << _ << std::endl; 60 | } 61 | 62 | { 63 | // Grab all the properties and print them. 64 | auto _ = co_await c.properties(); 65 | std::cout << "Should be 1234: " << _.last_result << std::endl; 66 | std::cout << "Should be 'client': " << _.owner << std::endl; 67 | } 68 | 69 | co_return; 70 | } 71 | 72 | int main() 73 | { 74 | sdbusplus::async::context ctx; 75 | ctx.spawn(startup(ctx)); 76 | ctx.spawn( 77 | sdbusplus::async::execution::just() | 78 | sdbusplus::async::execution::then([&ctx]() { ctx.request_stop(); })); 79 | ctx.run(); 80 | 81 | return 0; 82 | } 83 | -------------------------------------------------------------------------------- /example/calculator-server.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #include 6 | #include 7 | 8 | using Calculator_inherit = 9 | sdbusplus::server::object_t; 10 | 11 | /** Example implementation of net.poettering.Calculator */ 12 | struct Calculator : Calculator_inherit 13 | { 14 | /** Constructor */ 15 | Calculator(sdbusplus::bus_t& bus, const char* path) : 16 | Calculator_inherit(bus, path) 17 | {} 18 | 19 | /** Multiply (x*y), update lastResult */ 20 | int64_t multiply(int64_t x, int64_t y) override 21 | { 22 | return lastResult(x * y); 23 | } 24 | 25 | /** Divide (x/y), update lastResult 26 | * 27 | * Throws DivisionByZero on error. 28 | */ 29 | int64_t divide(int64_t x, int64_t y) override 30 | { 31 | using sdbusplus::error::net::poettering::Calculator::DivisionByZero; 32 | if (y == 0) 33 | { 34 | status(State::Error); 35 | throw DivisionByZero(); 36 | } 37 | 38 | return lastResult(x / y); 39 | } 40 | 41 | /** Clear lastResult, broadcast 'Cleared' signal */ 42 | void clear() override 43 | { 44 | auto v = lastResult(); 45 | lastResult(0); 46 | cleared(v); 47 | return; 48 | } 49 | }; 50 | 51 | int main() 52 | { 53 | // Create a new bus and affix an object manager for the subtree path we 54 | // intend to place objects at.. 55 | auto b = sdbusplus::bus::new_default(); 56 | sdbusplus::server::manager_t m{b, Calculator::instance_path}; 57 | 58 | // Reserve the dbus service name : net.poettering.Calculator 59 | b.request_name(Calculator::default_service); 60 | 61 | // Create a calculator object at /net/poettering/calculator 62 | Calculator c1{b, Calculator::instance_path}; 63 | 64 | // Handle dbus processing forever. 65 | b.process_loop(); 66 | } 67 | -------------------------------------------------------------------------------- /example/gen/meson.build: -------------------------------------------------------------------------------- 1 | # Generated file; do not modify. 2 | sdbuspp_gen_meson_ver = run_command( 3 | sdbuspp_gen_meson_prog, 4 | '--version', 5 | check: true, 6 | ).stdout().strip().split( 7 | '\n', 8 | )[0] 9 | 10 | if sdbuspp_gen_meson_ver != 'sdbus++-gen-meson version 10' 11 | warning('Generated meson files from wrong version of sdbus++-gen-meson.') 12 | warning( 13 | 'Expected "sdbus++-gen-meson version 10", got:', 14 | sdbuspp_gen_meson_ver, 15 | ) 16 | endif 17 | 18 | inst_markdown_dir = get_option('datadir') / 'doc' / meson.project_name() 19 | inst_registry_dir = get_option('datadir') / 'redfish-registry' / meson.project_name() 20 | 21 | generated_sources = [] 22 | generated_markdown = [] 23 | generated_registry = [] 24 | 25 | foreach d : yaml_selected_subdirs 26 | subdir(d) 27 | endforeach 28 | 29 | generated_headers = [] 30 | foreach s : generated_sources 31 | foreach f : s.to_list() 32 | if f.full_path().endswith('.hpp') 33 | generated_headers += f 34 | endif 35 | endforeach 36 | endforeach 37 | 38 | -------------------------------------------------------------------------------- /example/gen/net/meson.build: -------------------------------------------------------------------------------- 1 | # Generated file; do not modify. 2 | subdir('poettering') 3 | -------------------------------------------------------------------------------- /example/gen/net/poettering/Calculator/meson.build: -------------------------------------------------------------------------------- 1 | # Generated file; do not modify. 2 | 3 | sdbusplus_current_path = 'net/poettering/Calculator' 4 | 5 | generated_sources += custom_target( 6 | 'net/poettering/Calculator__cpp'.underscorify(), 7 | input: [ 8 | '../../../../yaml/net/poettering/Calculator.events.yaml', 9 | '../../../../yaml/net/poettering/Calculator.interface.yaml', 10 | ], 11 | output: [ 12 | 'event.cpp', 13 | 'event.hpp', 14 | 'common.hpp', 15 | 'server.hpp', 16 | 'server.cpp', 17 | 'aserver.hpp', 18 | 'client.hpp', 19 | ], 20 | depend_files: sdbusplusplus_depfiles, 21 | command: [ 22 | sdbuspp_gen_meson_prog, 23 | '--command', 24 | 'cpp', 25 | '--output', 26 | meson.current_build_dir(), 27 | '--tool', 28 | sdbusplusplus_prog, 29 | '--directory', 30 | meson.current_source_dir() / '../../../../yaml', 31 | 'net/poettering/Calculator', 32 | ], 33 | install: should_generate_cpp, 34 | install_dir: [ 35 | false, 36 | get_option('includedir') / sdbusplus_current_path, 37 | get_option('includedir') / sdbusplus_current_path, 38 | get_option('includedir') / sdbusplus_current_path, 39 | false, 40 | get_option('includedir') / sdbusplus_current_path, 41 | get_option('includedir') / sdbusplus_current_path, 42 | ], 43 | build_by_default: should_generate_cpp, 44 | ) 45 | 46 | -------------------------------------------------------------------------------- /example/gen/net/poettering/meson.build: -------------------------------------------------------------------------------- 1 | # Generated file; do not modify. 2 | subdir('Calculator') 3 | 4 | sdbusplus_current_path = 'net/poettering' 5 | 6 | generated_markdown += custom_target( 7 | 'net/poettering/Calculator__markdown'.underscorify(), 8 | input: [ 9 | '../../../yaml/net/poettering/Calculator.events.yaml', 10 | '../../../yaml/net/poettering/Calculator.interface.yaml', 11 | ], 12 | output: ['Calculator.md'], 13 | depend_files: sdbusplusplus_depfiles, 14 | command: [ 15 | sdbuspp_gen_meson_prog, 16 | '--command', 17 | 'markdown', 18 | '--output', 19 | meson.current_build_dir(), 20 | '--tool', 21 | sdbusplusplus_prog, 22 | '--directory', 23 | meson.current_source_dir() / '../../../yaml', 24 | 'net/poettering/Calculator', 25 | ], 26 | install: should_generate_markdown, 27 | install_dir: [inst_markdown_dir / sdbusplus_current_path], 28 | build_by_default: should_generate_markdown, 29 | ) 30 | 31 | generated_registry += custom_target( 32 | 'net/poettering/Calculator__registry'.underscorify(), 33 | input: ['../../../yaml/net/poettering/Calculator.events.yaml'], 34 | output: ['Calculator.json'], 35 | depend_files: sdbusplusplus_depfiles, 36 | command: [ 37 | sdbuspp_gen_meson_prog, 38 | '--command', 39 | 'registry', 40 | '--output', 41 | meson.current_build_dir(), 42 | '--tool', 43 | sdbusplusplus_prog, 44 | '--directory', 45 | meson.current_source_dir() / '../../../yaml', 46 | 'net/poettering/Calculator', 47 | ], 48 | install: should_generate_registry, 49 | install_dir: [inst_registry_dir / sdbusplus_current_path], 50 | build_by_default: should_generate_registry, 51 | ) 52 | 53 | -------------------------------------------------------------------------------- /example/gen/regenerate-meson: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | cd "$(dirname "$0")" || exit 3 | export PATH="${PWD}/../../tools:${PATH}" 4 | sdbus++-gen-meson --command meson --directory ../yaml --output . 5 | find . -name "meson.build" -exec meson format -i {} + 6 | -------------------------------------------------------------------------------- /example/gen/run-ci: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | cd "$(dirname "$0")" || exit 3 | ./regenerate-meson || exit 4 | rc=0 5 | git --no-pager diff --exit-code -- . || rc=$? 6 | untracked="$(git ls-files --others --exclude-standard -- .)" || rc=$? 7 | if [[ -n "${untracked}" ]]; then 8 | echo "Untracked files:" >&2 9 | echo "${untracked}" >&2 10 | rc=1 11 | fi 12 | if (( rc != 0 )); then 13 | echo "Generated meson files differ from expected values" >&2 14 | exit 1 15 | fi 16 | -------------------------------------------------------------------------------- /example/list-users.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include 4 | #include 5 | 6 | /** An example dbus client application. 7 | * Calls org.freedesktop.login1's ListUsers interface to find all active 8 | * users in the system and displays their username. 9 | */ 10 | 11 | int main() 12 | { 13 | using namespace sdbusplus; 14 | 15 | auto b = bus::new_default_system(); 16 | auto m = 17 | b.new_method_call("org.freedesktop.login1", "/org/freedesktop/login1", 18 | "org.freedesktop.login1.Manager", "ListUsers"); 19 | auto reply = b.call(m); 20 | 21 | using return_type = 22 | std::vector>; 23 | auto users = reply.unpack(); 24 | 25 | for (auto& user : users) 26 | { 27 | std::cout << std::get(user) << "\n"; 28 | } 29 | 30 | return 0; 31 | } 32 | -------------------------------------------------------------------------------- /example/meson.build: -------------------------------------------------------------------------------- 1 | executable('list-users', 'list-users.cpp', dependencies: sdbusplus_dep) 2 | 3 | has_asio = meson.get_compiler('cpp').has_header_symbol( 4 | 'boost/asio.hpp', 5 | 'boost::asio::io_context', 6 | required: false, 7 | ) 8 | asio_dep = sdbusplus_dep 9 | if not has_asio 10 | asio_dep = disabler() 11 | endif 12 | 13 | assert( 14 | not get_option('examples').allowed() or has_asio, 15 | 'Boost is required when examples are enabled', 16 | ) 17 | 18 | executable( 19 | 'asio-example', 20 | 'asio-example.cpp', 21 | dependencies: [ 22 | asio_dep, 23 | dependency( 24 | 'boost', 25 | modules: ['coroutine', 'context'], 26 | disabler: true, 27 | required: false, 28 | ), 29 | ], 30 | ) 31 | 32 | executable( 33 | 'coroutine-example', 34 | 'coroutine-example.cpp', 35 | dependencies: [sdbusplus_dep], 36 | ) 37 | 38 | executable('register-property', 'register-property.cpp', dependencies: asio_dep) 39 | 40 | executable( 41 | 'get-all-properties', 42 | 'get-all-properties.cpp', 43 | dependencies: asio_dep, 44 | ) 45 | 46 | yaml_selected_subdirs = ['net'] 47 | subdir('gen') 48 | 49 | executable( 50 | 'calculator-server', 51 | 'calculator-server.cpp', 52 | generated_sources, 53 | implicit_include_directories: false, 54 | include_directories: include_directories('gen'), 55 | dependencies: sdbusplus_dep, 56 | ) 57 | 58 | executable( 59 | 'calculator-aserver', 60 | 'calculator-aserver.cpp', 61 | generated_sources, 62 | implicit_include_directories: false, 63 | include_directories: include_directories('gen'), 64 | dependencies: sdbusplus_dep, 65 | ) 66 | 67 | executable( 68 | 'calculator-client', 69 | 'calculator-client.cpp', 70 | generated_sources, 71 | implicit_include_directories: false, 72 | include_directories: include_directories('gen'), 73 | dependencies: sdbusplus_dep, 74 | ) 75 | -------------------------------------------------------------------------------- /example/yaml/net/poettering/Calculator.events.yaml: -------------------------------------------------------------------------------- 1 | version: 0.0.0 2 | 3 | errors: 4 | - name: DivisionByZero 5 | severity: warning 6 | errno: EDOM 7 | en: 8 | message: Attempted to divide by zero. 9 | 10 | - name: PermissionDenied 11 | severity: warning 12 | errno: EPERM 13 | en: 14 | message: Insufficient privileges for operation. 15 | 16 | events: 17 | - name: Cleared 18 | en: 19 | description: The calculator is cleared. 20 | message: The calculator is cleared. 21 | -------------------------------------------------------------------------------- /example/yaml/net/poettering/Calculator.interface.yaml: -------------------------------------------------------------------------------- 1 | description: > 2 | An example interface originally described as part of the announcement of new 3 | sd-bus interfaces at: 4 | http://0pointer.net/blog/the-new-sd-bus-api-of-systemd.html 5 | methods: 6 | - name: Multiply 7 | description: > 8 | Multiplies two integers 'x' and 'y' and returns the result. 9 | parameters: 10 | - name: x 11 | type: int64 12 | description: > 13 | The first integer to multiply. 14 | - name: y 15 | type: int64 16 | description: > 17 | The second integer to multiply. 18 | default: 1 19 | returns: 20 | - name: z 21 | type: int64 22 | description: > 23 | The result of (x*y). 24 | - name: Divide 25 | description: > 26 | Divides two integers 'x' and 'y' and returns the result. 27 | parameters: 28 | - name: x 29 | type: int64 30 | description: > 31 | The first integer to divide. 32 | - name: y 33 | type: int64 34 | description: > 35 | The second integer to divide. 36 | default: 1 37 | returns: 38 | - name: z 39 | type: int64 40 | description: > 41 | The result of (x/y). 42 | errors: 43 | - self.DivisionByZero 44 | - name: Clear 45 | flags: 46 | - unprivileged 47 | - no_reply 48 | description: > 49 | Reset the LastResult property to zero. 50 | properties: 51 | - name: LastResult 52 | type: int64 53 | default: 0 54 | description: > 55 | The result of the most recent calculation. 56 | - name: Status 57 | type: enum[self.State] 58 | default: Success 59 | flags: 60 | - const 61 | description: > 62 | The current state of the Calculator. 63 | - name: Owner 64 | type: string 65 | description: > 66 | The name of the owner of the Calculator. 67 | errors: 68 | - self.PermissionDenied 69 | signals: 70 | - name: Cleared 71 | description: > 72 | Signal indicating the LastReset property has been set to zero by the 73 | 'Clear' method. 74 | properties: 75 | - type: int64 76 | description: > 77 | Value of LastReset prior to Clear. 78 | enumerations: 79 | - name: State 80 | description: > 81 | Identifies if the service has encountered an error or not. 82 | values: 83 | - name: Success 84 | description: > 85 | No error has been encountered. 86 | - name: Error 87 | description: > 88 | The service has encountered an error. 89 | 90 | paths: 91 | - instance: /net/poettering/calculator 92 | description: Expected path of the instance. 93 | 94 | service_names: 95 | - default: net.poettering.Calculator 96 | description: Expected service name for the instance. 97 | -------------------------------------------------------------------------------- /include/sdbusplus/asio/detail/async_send_handler.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | // Copyright (c) 2018 Intel Corporation 3 | // 4 | // Licensed under the Apache License, Version 2.0 (the "License"); 5 | // you may not use this file except in compliance with the License. 6 | // You may obtain a copy of the License at 7 | // 8 | // http://www.apache.org/licenses/LICENSE-2.0 9 | // 10 | // Unless required by applicable law or agreed to in writing, software 11 | // distributed under the License is distributed on an "AS IS" BASIS, 12 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | // See the License for the specific language governing permissions and 14 | // limitations under the License. 15 | */ 16 | #pragma once 17 | 18 | #include 19 | 20 | #include 21 | #include 22 | #include 23 | 24 | namespace sdbusplus 25 | { 26 | namespace asio 27 | { 28 | namespace detail 29 | { 30 | 31 | /* Class meant for converting a static callback, and void* userdata from sd-bus 32 | * back into a structured class to be returned to the user. 33 | */ 34 | template 35 | struct unpack_userdata 36 | { 37 | CompletionToken handler_; 38 | 39 | static int do_unpack(sd_bus_message* mesg, void* userdata, 40 | sd_bus_error* /*error*/) 41 | { 42 | if (userdata == nullptr) 43 | { 44 | return -EINVAL; 45 | } 46 | 47 | // Take RAII ownership of the pointer again 48 | using self_t = unpack_userdata; 49 | std::unique_ptr context(static_cast(userdata)); 50 | 51 | if (mesg == nullptr) 52 | { 53 | return -EINVAL; 54 | } 55 | message_t message(mesg); 56 | auto ec = make_error_code( 57 | static_cast(message.get_errno())); 58 | context->handler_(ec, message); 59 | return 0; 60 | } 61 | 62 | explicit unpack_userdata(CompletionToken&& handler) : 63 | handler_(std::forward(handler)) 64 | {} 65 | }; 66 | 67 | class async_send_handler 68 | { 69 | sd_bus* bus; 70 | message_t& mesg; 71 | uint64_t timeout; 72 | 73 | public: 74 | template 75 | void operator()(CompletionToken&& token) 76 | { 77 | using unpack_t = unpack_userdata; 78 | auto context = std::make_unique(std::move(token)); 79 | int ec = 80 | sd_bus_call_async(bus, nullptr, mesg.get(), &unpack_t::do_unpack, 81 | context.get(), timeout); 82 | if (ec < 0) 83 | { 84 | auto err = 85 | make_error_code(static_cast(ec)); 86 | context->handler_(err, mesg); 87 | return; 88 | } 89 | // If the call succeeded, sd-bus owns the pointer now, so release it 90 | // without freeing. 91 | context.release(); 92 | } 93 | 94 | async_send_handler(sd_bus* busIn, message_t& mesgIn, uint64_t timeoutIn) : 95 | bus(busIn), mesg(mesgIn), timeout(timeoutIn) 96 | {} 97 | }; 98 | } // namespace detail 99 | } // namespace asio 100 | } // namespace sdbusplus 101 | -------------------------------------------------------------------------------- /include/sdbusplus/async.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | // IWYU pragma: begin_exports 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | // IWYU pragma: end_exports 13 | -------------------------------------------------------------------------------- /include/sdbusplus/async/execution.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | // The upstream code has some warnings under GCC, so turn them off 4 | // as needed. 5 | 6 | #pragma GCC diagnostic push 7 | #ifdef __clang__ 8 | #pragma clang diagnostic ignored "-Wunused-parameter" 9 | #pragma clang diagnostic ignored "-Wnon-pod-varargs" 10 | #pragma clang diagnostic ignored "-Winconsistent-missing-override" 11 | #pragma clang diagnostic ignored "-Wdeprecated-copy" 12 | #else 13 | #pragma GCC diagnostic ignored "-Wnon-template-friend" 14 | #endif 15 | #pragma GCC diagnostic ignored "-Wmissing-field-initializers" 16 | #pragma GCC diagnostic ignored "-Wunused-parameter" 17 | #include 18 | #include 19 | #include 20 | #pragma GCC diagnostic pop 21 | 22 | // Add std::execution as sdbusplus::async::execution so that we can simplify 23 | // reference to any parts of it we use internally. 24 | namespace sdbusplus::async 25 | { 26 | namespace execution = stdexec; 27 | using async_scope = exec::async_scope; 28 | } // namespace sdbusplus::async 29 | -------------------------------------------------------------------------------- /include/sdbusplus/async/stdexec/__detail/__completion_signatures.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2021-2024 NVIDIA Corporation 3 | * 4 | * Licensed under the Apache License Version 2.0 with LLVM Exceptions 5 | * (the "License"); you may not use this file except in compliance with 6 | * the License. You may obtain a copy of the License at 7 | * 8 | * https://llvm.org/LICENSE.txt 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | #pragma once 17 | 18 | #include "__execution_fwd.hpp" 19 | 20 | // include these after __execution_fwd.hpp 21 | #include "__concepts.hpp" 22 | #include "__diagnostics.hpp" 23 | #include "__meta.hpp" 24 | 25 | namespace stdexec 26 | { 27 | ///////////////////////////////////////////////////////////////////////////// 28 | // completion_signatures 29 | namespace __sigs 30 | { 31 | template 32 | inline constexpr bool __is_compl_sig = true; 33 | template 34 | inline constexpr bool __is_compl_sig = true; 35 | template <> 36 | inline constexpr bool __is_compl_sig = true; 37 | 38 | template 39 | inline constexpr bool __is_completion_signatures = false; 40 | template 41 | inline constexpr bool 42 | __is_completion_signatures> = true; 43 | } // namespace __sigs 44 | 45 | template 46 | struct completion_signatures 47 | {}; 48 | 49 | template 50 | concept __valid_completion_signatures = // 51 | __same_as<__ok_t<_Completions>, __msuccess> && 52 | __sigs::__is_completion_signatures<_Completions>; 53 | 54 | template 55 | using __unrecognized_sender_error = // 56 | __mexception<_UNRECOGNIZED_SENDER_TYPE_<>, _WITH_SENDER_<_Sender>, 57 | _WITH_ENVIRONMENT_<_Env>>; 58 | } // namespace stdexec 59 | -------------------------------------------------------------------------------- /include/sdbusplus/async/stdexec/__detail/__diagnostics.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2021-2024 NVIDIA Corporation 3 | * 4 | * Licensed under the Apache License Version 2.0 with LLVM Exceptions 5 | * (the "License"); you may not use this file except in compliance with 6 | * the License. You may obtain a copy of the License at 7 | * 8 | * https://llvm.org/LICENSE.txt 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | #pragma once 17 | 18 | #include "__meta.hpp" 19 | 20 | namespace stdexec 21 | { 22 | namespace __detail 23 | { 24 | template 25 | extern __q<__midentity> __name_of_v; 26 | 27 | template 28 | using __name_of_fn = decltype(__name_of_v<_Ty>); 29 | 30 | template 31 | using __name_of = __minvoke<__name_of_fn<_Ty>, _Ty>; 32 | } // namespace __detail 33 | 34 | // A utility for pretty-printing type names in diagnostics 35 | template 36 | using __name_of = __detail::__name_of<_Ty>; 37 | 38 | namespace __errs 39 | { 40 | inline constexpr __mstring __unrecognized_sender_type_diagnostic = 41 | "The given type cannot be used as a sender with the given environment " 42 | "because the attempt to compute the completion signatures failed."_mstr; 43 | 44 | template 45 | struct _WITH_SENDER_; 46 | 47 | template 48 | struct _WITH_SENDERS_; 49 | } // namespace __errs 50 | 51 | struct _WHERE_; 52 | 53 | struct _IN_ALGORITHM_; 54 | 55 | template <__mstring _Diagnostic = __errs::__unrecognized_sender_type_diagnostic> 56 | struct _UNRECOGNIZED_SENDER_TYPE_; 57 | 58 | template 59 | using _WITH_SENDER_ = __errs::_WITH_SENDER_<__name_of<_Sender>>; 60 | 61 | template 62 | using _WITH_SENDERS_ = __errs::_WITH_SENDERS_<__name_of<_Senders>...>; 63 | 64 | template 65 | struct _WITH_ENVIRONMENT_; 66 | 67 | template 68 | struct _WITH_TYPE_; 69 | 70 | template 71 | struct _WITH_RECEIVER_; 72 | 73 | template 74 | struct _MISSING_COMPLETION_SIGNAL_; 75 | 76 | template 77 | struct _WITH_COMPLETION_SIGNATURE_; 78 | 79 | template 80 | struct _WITH_FUNCTION_; 81 | 82 | template 83 | struct _WITH_ARGUMENTS_; 84 | 85 | template 86 | struct _WITH_QUERY_; 87 | 88 | struct _SENDER_TYPE_IS_NOT_COPYABLE_; 89 | 90 | inline constexpr __mstring __not_callable_diag = 91 | "The specified function is not callable with the arguments provided."_mstr; 92 | 93 | template <__mstring _Context, __mstring _Diagnostic = __not_callable_diag> 94 | struct _NOT_CALLABLE_; 95 | 96 | template 97 | struct _CANNOT_PIPE_INTO_A_SENDER_ 98 | {}; 99 | 100 | template 101 | using __bad_pipe_sink_t = 102 | __mexception<_CANNOT_PIPE_INTO_A_SENDER_<>, _WITH_SENDER_<_Sender>>; 103 | 104 | template <__mstring _Context> 105 | struct __callable_error 106 | { 107 | template 108 | using __f = // 109 | __mexception< // 110 | _NOT_CALLABLE_<_Context>, _WITH_FUNCTION_<_Fun>, 111 | _WITH_ARGUMENTS_<_Args...>>; 112 | }; 113 | } // namespace stdexec 114 | -------------------------------------------------------------------------------- /include/sdbusplus/async/stdexec/__detail/__execute.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2021-2024 NVIDIA Corporation 3 | * 4 | * Licensed under the Apache License Version 2.0 with LLVM Exceptions 5 | * (the "License"); you may not use this file except in compliance with 6 | * the License. You may obtain a copy of the License at 7 | * 8 | * https://llvm.org/LICENSE.txt 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | #pragma once 17 | 18 | #include "__completion_signatures.hpp" 19 | #include "__concepts.hpp" 20 | #include "__cpo.hpp" 21 | #include "__execution_fwd.hpp" 22 | #include "__meta.hpp" 23 | #include "__receivers.hpp" 24 | #include "__schedulers.hpp" 25 | #include "__senders.hpp" 26 | #include "__submit.hpp" 27 | #include "__tag_invoke.hpp" 28 | #include "__transform_sender.hpp" 29 | #include "__type_traits.hpp" 30 | 31 | #include 32 | 33 | namespace stdexec 34 | { 35 | ///////////////////////////////////////////////////////////////////////////// 36 | // [execution.execute] 37 | namespace __execute_ 38 | { 39 | template 40 | struct __as_receiver 41 | { 42 | using receiver_concept = receiver_t; 43 | _Fun __fun_; 44 | 45 | void set_value() noexcept 46 | { 47 | // terminates on exception: 48 | __fun_(); 49 | } 50 | 51 | [[noreturn]] void set_error(std::exception_ptr) noexcept 52 | { 53 | std::terminate(); 54 | } 55 | 56 | void set_stopped() noexcept {} 57 | }; 58 | 59 | struct execute_t 60 | { 61 | template 62 | requires __callable<_Fun&> && move_constructible<_Fun> 63 | void operator()(_Scheduler&& __sched, _Fun __fun) const noexcept(false) 64 | { 65 | // Look for a legacy customization 66 | if constexpr (tag_invocable) 67 | { 68 | tag_invoke(execute_t{}, static_cast<_Scheduler&&>(__sched), 69 | static_cast<_Fun&&>(__fun)); 70 | } 71 | else 72 | { 73 | auto __domain = query_or(get_domain, __sched, default_domain()); 74 | stdexec::apply_sender(__domain, *this, 75 | schedule(static_cast<_Scheduler&&>(__sched)), 76 | static_cast<_Fun&&>(__fun)); 77 | } 78 | } 79 | 80 | template _Sender, class _Fun> 81 | requires __callable<_Fun&> && move_constructible<_Fun> 82 | void apply_sender(_Sender&& __sndr, _Fun __fun) const noexcept(false) 83 | { 84 | __submit(static_cast<_Sender&&>(__sndr), 85 | __as_receiver<_Fun>{static_cast<_Fun&&>(__fun)}); 86 | } 87 | }; 88 | } // namespace __execute_ 89 | 90 | using __execute_::execute_t; 91 | inline constexpr execute_t execute{}; 92 | } // namespace stdexec 93 | -------------------------------------------------------------------------------- /include/sdbusplus/async/stdexec/__detail/__force_include.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2022 NVIDIA Corporation 3 | * 4 | * Licensed under the Apache License Version 2.0 with LLVM Exceptions 5 | * (the "License"); you may not use this file except in compliance with 6 | * the License. You may obtain a copy of the License at 7 | * 8 | * https://llvm.org/LICENSE.txt 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | #if defined(__clang__) && defined(__CUDACC__) 18 | 19 | #ifdef __noinline__ 20 | #undef __noinline__ 21 | #endif 22 | 23 | #endif 24 | -------------------------------------------------------------------------------- /include/sdbusplus/async/stdexec/__detail/__inline_scheduler.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2021-2024 NVIDIA Corporation 3 | * 4 | * Licensed under the Apache License Version 2.0 with LLVM Exceptions 5 | * (the "License"); you may not use this file except in compliance with 6 | * the License. You may obtain a copy of the License at 7 | * 8 | * https://llvm.org/LICENSE.txt 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | #pragma once 17 | 18 | #include "__basic_sender.hpp" 19 | #include "__cpo.hpp" 20 | #include "__env.hpp" 21 | #include "__execution_fwd.hpp" 22 | #include "__receivers.hpp" 23 | #include "__schedulers.hpp" 24 | #include "__utility.hpp" 25 | 26 | namespace stdexec 27 | { 28 | namespace __inln 29 | { 30 | struct __schedule_t 31 | {}; 32 | 33 | struct __scheduler 34 | { 35 | using __t = __scheduler; 36 | using __id = __scheduler; 37 | 38 | template 39 | STDEXEC_ATTRIBUTE((host, device)) 40 | STDEXEC_MEMFN_DECL(auto schedule)(this __scheduler) 41 | { 42 | return __make_sexpr<_Tag>(); 43 | } 44 | 45 | auto query(get_forward_progress_guarantee_t) const noexcept 46 | -> forward_progress_guarantee 47 | { 48 | return forward_progress_guarantee::weakly_parallel; 49 | } 50 | 51 | auto operator==(const __scheduler&) const noexcept -> bool = default; 52 | }; 53 | 54 | struct __env 55 | { 56 | static constexpr bool query(__is_scheduler_affine_t) noexcept 57 | { 58 | return true; 59 | } 60 | 61 | constexpr auto query(get_completion_scheduler_t) const noexcept 62 | -> __scheduler 63 | { 64 | return {}; 65 | } 66 | }; 67 | } // namespace __inln 68 | 69 | template <> 70 | struct __sexpr_impl<__inln::__schedule_t> : __sexpr_defaults 71 | { 72 | static constexpr auto get_attrs = // 73 | [](__ignore) noexcept { return __inln::__env(); }; 74 | 75 | static constexpr auto get_completion_signatures = // 76 | [](__ignore, 77 | __ignore = {}) noexcept -> completion_signatures { 78 | return {}; 79 | }; 80 | 81 | static constexpr auto start = // 82 | [](__ignore, _Receiver& __rcvr) noexcept -> void { 83 | stdexec::set_value(static_cast<_Receiver&&>(__rcvr)); 84 | }; 85 | }; 86 | 87 | static_assert(__is_scheduler_affine>); 88 | } // namespace stdexec 89 | -------------------------------------------------------------------------------- /include/sdbusplus/async/stdexec/__detail/__intrusive_mpsc_queue.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) Dmitiy V'jukov 3 | * Copyright (c) 2024 Maikel Nadolski 4 | * Copyright (c) 2024 NVIDIA Corporation 5 | * 6 | * Licensed under the Apache License Version 2.0 with LLVM Exceptions 7 | * (the "License"); you may not use this file except in compliance with 8 | * the License. You may obtain a copy of the License at 9 | * 10 | * https://llvm.org/LICENSE.txt 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | 19 | // general design of this MPSC queue is taken from 20 | // https://www.1024cores.net/home/lock-free-algorithms/queues/intrusive-mpsc-node-based-queue 21 | 22 | #pragma once 23 | 24 | #include 25 | 26 | #include 27 | 28 | namespace stdexec 29 | { 30 | template 31 | class __intrusive_mpsc_queue; 32 | 33 | template _Node::* _Next> 34 | class __intrusive_mpsc_queue<_Next> 35 | { 36 | std::atomic __back_{&__nil_}; 37 | void* __front_{&__nil_}; 38 | std::atomic<_Node*> __nil_ = nullptr; 39 | 40 | void push_back_nil() 41 | { 42 | __nil_.store(nullptr, std::memory_order_relaxed); 43 | _Node* __prev = static_cast<_Node*>( 44 | __back_.exchange(&__nil_, std::memory_order_acq_rel)); 45 | (__prev->*_Next).store(&__nil_, std::memory_order_release); 46 | } 47 | 48 | public: 49 | bool push_back(_Node* __new_node) noexcept 50 | { 51 | (__new_node->*_Next).store(nullptr, std::memory_order_relaxed); 52 | void* __prev_back = 53 | __back_.exchange(__new_node, std::memory_order_acq_rel); 54 | bool __is_nil = __prev_back == static_cast(&__nil_); 55 | if (__is_nil) 56 | { 57 | __nil_.store(__new_node, std::memory_order_release); 58 | } 59 | else 60 | { 61 | (static_cast<_Node*>(__prev_back)->*_Next) 62 | .store(__new_node, std::memory_order_release); 63 | } 64 | return __is_nil; 65 | } 66 | 67 | _Node* pop_front() noexcept 68 | { 69 | if (__front_ == static_cast(&__nil_)) 70 | { 71 | _Node* __next = __nil_.load(std::memory_order_acquire); 72 | if (!__next) 73 | { 74 | return nullptr; 75 | } 76 | __front_ = __next; 77 | } 78 | _Node* __front = static_cast<_Node*>(__front_); 79 | void* __next = (__front->*_Next).load(std::memory_order_acquire); 80 | if (__next) 81 | { 82 | __front_ = __next; 83 | return __front; 84 | } 85 | STDEXEC_ASSERT(!__next); 86 | push_back_nil(); 87 | do 88 | { 89 | __spin_loop_pause(); 90 | __next = (__front->*_Next).load(std::memory_order_acquire); 91 | } while (!__next); 92 | __front_ = __next; 93 | return __front; 94 | } 95 | }; 96 | } // namespace stdexec 97 | -------------------------------------------------------------------------------- /include/sdbusplus/async/stdexec/__detail/__operation_states.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2021-2024 NVIDIA Corporation 3 | * 4 | * Licensed under the Apache License Version 2.0 with LLVM Exceptions 5 | * (the "License"); you may not use this file except in compliance with 6 | * the License. You may obtain a copy of the License at 7 | * 8 | * https://llvm.org/LICENSE.txt 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | #pragma once 17 | 18 | #include "__execution_fwd.hpp" 19 | 20 | // include these after __execution_fwd.hpp 21 | #include "__concepts.hpp" 22 | #include "__tag_invoke.hpp" 23 | 24 | #include 25 | 26 | namespace stdexec 27 | { 28 | // operation state tag type 29 | struct operation_state_t 30 | {}; 31 | 32 | ///////////////////////////////////////////////////////////////////////////// 33 | // [execution.op_state] 34 | namespace __start 35 | { 36 | struct start_t 37 | { 38 | template <__same_as _Self, class _OpState> 39 | STDEXEC_ATTRIBUTE((always_inline)) 40 | friend auto tag_invoke(_Self, _OpState& __op) noexcept 41 | -> decltype(__op.start()) 42 | { 43 | static_assert(noexcept(__op.start()), 44 | "start() members must be noexcept"); 45 | static_assert(__same_as, 46 | "start() members must return void"); 47 | __op.start(); 48 | } 49 | 50 | template 51 | requires tag_invocable 52 | STDEXEC_ATTRIBUTE((always_inline)) 53 | void operator()(_Op& __op) const noexcept 54 | { 55 | static_assert(nothrow_tag_invocable); 56 | (void)tag_invoke(start_t{}, __op); 57 | } 58 | }; 59 | } // namespace __start 60 | 61 | using __start::start_t; 62 | inline constexpr start_t start{}; 63 | 64 | ///////////////////////////////////////////////////////////////////////////// 65 | // [execution.op_state] 66 | template 67 | concept operation_state = // 68 | destructible<_Op> && // 69 | std::is_object_v<_Op> && // 70 | requires(_Op& __op) { // 71 | stdexec::start(__op); 72 | }; 73 | } // namespace stdexec 74 | -------------------------------------------------------------------------------- /include/sdbusplus/async/stdexec/__detail/__senders_core.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2021-2024 NVIDIA Corporation 3 | * 4 | * Licensed under the Apache License Version 2.0 with LLVM Exceptions 5 | * (the "License"); you may not use this file except in compliance with 6 | * the License. You may obtain a copy of the License at 7 | * 8 | * https://llvm.org/LICENSE.txt 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | #pragma once 17 | 18 | #include "__execution_fwd.hpp" 19 | 20 | // include these after __execution_fwd.hpp 21 | #include "__awaitable.hpp" 22 | #include "__completion_signatures.hpp" 23 | #include "__concepts.hpp" 24 | #include "__domain.hpp" 25 | #include "__env.hpp" 26 | #include "__receivers.hpp" 27 | #include "__type_traits.hpp" 28 | 29 | namespace stdexec 30 | { 31 | ///////////////////////////////////////////////////////////////////////////// 32 | // [execution.senders] 33 | struct sender_t 34 | { 35 | using sender_concept = sender_t; 36 | }; 37 | 38 | namespace __detail 39 | { 40 | template 41 | concept __enable_sender = // 42 | derived_from || 43 | requires { typename _Sender::is_sender; } // NOT TO SPEC back compat 44 | || __awaitable<_Sender, __env::__promise>; 45 | } // namespace __detail 46 | 47 | template 48 | inline constexpr bool enable_sender = __detail::__enable_sender<_Sender>; 49 | 50 | template 51 | concept sender = // 52 | enable_sender<__decay_t<_Sender>> // 53 | && environment_provider<__cref_t<_Sender>> // 54 | && __detail::__consistent_completion_domains<_Sender> // 55 | && move_constructible<__decay_t<_Sender>> // 56 | && constructible_from<__decay_t<_Sender>, _Sender>; 57 | 58 | template 59 | concept sender_in = 60 | (sizeof...(_Env) <= 1) // 61 | && sender<_Sender> // 62 | && requires(_Sender&& __sndr, _Env&&... __env) { 63 | { 64 | get_completion_signatures(static_cast<_Sender&&>(__sndr), 65 | static_cast<_Env&&>(__env)...) 66 | } -> __valid_completion_signatures; 67 | }; 68 | } // namespace stdexec 69 | -------------------------------------------------------------------------------- /include/sdbusplus/async/stdexec/__detail/__spin_loop_pause.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2023 Maikel Nadolski 3 | * Copyright (c) 2023 NVIDIA Corporation 4 | * 5 | * Licensed under the Apache License Version 2.0 with LLVM Exceptions 6 | * (the "License"); you may not use this file except in compliance with 7 | * the License. You may obtain a copy of the License at 8 | * 9 | * https://llvm.org/LICENSE.txt 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | #pragma once 18 | 19 | #include "../../stdexec/__detail/__config.hpp" 20 | 21 | // The below code for spin_loop_pause is taken from 22 | // https://github.com/max0x7ba/atomic_queue/blob/master/include/atomic_queue/defs.h 23 | // Copyright (c) 2019 Maxim Egorushkin. MIT License. 24 | 25 | #if defined(__x86_64__) || defined(_M_X64) || defined(__i386__) || \ 26 | defined(_M_IX86) 27 | #if STDEXEC_MSVC_HEADERS() 28 | #include 29 | #endif 30 | namespace stdexec 31 | { 32 | STDEXEC_ATTRIBUTE((always_inline)) 33 | static void __spin_loop_pause() noexcept 34 | { 35 | #if STDEXEC_MSVC_HEADERS() 36 | _mm_pause(); 37 | #else 38 | __builtin_ia32_pause(); 39 | #endif 40 | } 41 | } // namespace stdexec 42 | #elif defined(__arm__) || defined(__aarch64__) || defined(_M_ARM64) 43 | namespace stdexec 44 | { 45 | STDEXEC_ATTRIBUTE((always_inline)) 46 | static void __spin_loop_pause() noexcept 47 | { 48 | #if (defined(__ARM_ARCH_6K__) || defined(__ARM_ARCH_6Z__) || \ 49 | defined(__ARM_ARCH_6ZK__) || defined(__ARM_ARCH_6T2__) || \ 50 | defined(__ARM_ARCH_7__) || defined(__ARM_ARCH_7A__) || \ 51 | defined(__ARM_ARCH_7R__) || defined(__ARM_ARCH_7M__) || \ 52 | defined(__ARM_ARCH_7S__) || defined(__ARM_ARCH_8A__) || \ 53 | defined(__aarch64__)) 54 | asm volatile("yield" ::: "memory"); 55 | #elif defined(_M_ARM64) 56 | __yield(); 57 | #else 58 | asm volatile("nop" ::: "memory"); 59 | #endif 60 | } 61 | } // namespace stdexec 62 | #else 63 | namespace stdexec 64 | { 65 | STDEXEC_ATTRIBUTE((always_inline)) 66 | static void __spin_loop_pause() noexcept {} 67 | } // namespace stdexec 68 | #endif 69 | -------------------------------------------------------------------------------- /include/sdbusplus/async/stdexec/__detail/__stop_token.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2021-2022 Facebook, Inc. and its affiliates 3 | * Copyright (c) 2021-2024 NVIDIA Corporation 4 | * 5 | * Licensed under the Apache License Version 2.0 with LLVM Exceptions 6 | * (the "License"); you may not use this file except in compliance with 7 | * the License. You may obtain a copy of the License at 8 | * 9 | * https://llvm.org/LICENSE.txt 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | #pragma once 18 | 19 | #include "__concepts.hpp" 20 | #include "__execution_fwd.hpp" 21 | 22 | namespace stdexec 23 | { 24 | namespace __stok 25 | { 26 | template