From 846e61c0fb5161a16c5719211f74bb784ffa005b Mon Sep 17 00:00:00 2001 From: Joseph Huber Date: Thu, 12 Feb 2026 09:15:15 -0600 Subject: [PATCH] [libc] Small change to accept lambda types in rpc::dispatch Summary: This change allows lambdas to be used in the RPC dispatching functions. Just requires an extra function trait to convert a lambda with no captures into a function pointer. Also rearranged where the `Port` lives because it looks better no that we may use a lambda and it's more consistent with the dispatch usage (putting the client at the start). --- libc/shared/rpc_dispatch.h | 2 +- libc/shared/rpc_util.h | 6 +++++- offload/test/libc/rpc_callback.cpp | 22 ++++++++++++++-------- 3 files changed, 20 insertions(+), 10 deletions(-) diff --git a/libc/shared/rpc_dispatch.h b/libc/shared/rpc_dispatch.h index 98a7cace4ee6..1a385c1b7d82 100644 --- a/libc/shared/rpc_dispatch.h +++ b/libc/shared/rpc_dispatch.h @@ -217,7 +217,7 @@ dispatch(rpc::Client &client, FnTy, CallArgs... args) { // Invoke a function on the server on behalf of the client. Recieves the // arguments through the interface and forwards them to the function. template -RPC_ATTRS constexpr void invoke(FnTy fn, rpc::Server::Port &port) { +RPC_ATTRS constexpr void invoke(rpc::Server::Port &port, FnTy fn) { using Traits = function_traits; using RetTy = typename Traits::return_type; using TupleTy = typename Traits::arg_types; diff --git a/libc/shared/rpc_util.h b/libc/shared/rpc_util.h index a7d9d72a4b11..171caff1140f 100644 --- a/libc/shared/rpc_util.h +++ b/libc/shared/rpc_util.h @@ -440,13 +440,17 @@ RPC_ATTRS constexpr uint64_t string_length(const char *s) { return static_cast(end - s + 1); } -/// Helper for dealing with function types. +/// Helper for dealing with function pointers and lambda types. template struct function_traits; template struct function_traits { using return_type = R; using arg_types = rpc::tuple; static constexpr uint64_t ARITY = sizeof...(Args); }; +template T &&declval(); +template +struct function_traits + : function_traits>())> {}; template RPC_ATTRS constexpr T max(const T &a, const U &b) { diff --git a/offload/test/libc/rpc_callback.cpp b/offload/test/libc/rpc_callback.cpp index 3246e5a34bb0..f313541e58d1 100644 --- a/offload/test/libc/rpc_callback.cpp +++ b/offload/test/libc/rpc_callback.cpp @@ -77,7 +77,10 @@ int c_string(const char *s) { int empty() { return 42; } // 7. Divergent values. -void divergent(int *) {} +void divergent(int *p) { + assert(p); + *p = *p; +} //===------------------------------------------------------------------------=== // RPC client dispatch. @@ -117,25 +120,28 @@ template rpc::Status handleOpcodesImpl(rpc::Server::Port &Port) { switch (Port.get_opcode()) { case FOO_OPCODE: - rpc::invoke(foo, Port); + rpc::invoke(Port, foo); break; case VOID_OPCODE: - rpc::invoke(void_fn, Port); + rpc::invoke(Port, void_fn); break; case WRITEBACK_OPCODE: - rpc::invoke(writeback_fn, Port); + rpc::invoke(Port, writeback_fn); break; case CONST_PTR_OPCODE: - rpc::invoke(sum_const, Port); + rpc::invoke(Port, sum_const); break; case STRING_OPCODE: - rpc::invoke(c_string, Port); + rpc::invoke(Port, c_string); break; case EMPTY_OPCODE: - rpc::invoke(empty, Port); + rpc::invoke(Port, empty); break; case DIVERGENT_OPCODE: - rpc::invoke(divergent, Port); + rpc::invoke(Port, [](int *p) { + assert(p); + *p = *p; + }); break; default: return rpc::RPC_UNHANDLED_OPCODE;