From 8b75ae8b039754b5d6443b1ccd16214fbb8f6344 Mon Sep 17 00:00:00 2001 From: Ivan FB Date: Sun, 3 May 2026 17:33:06 +0200 Subject: [PATCH] enhance async cpp Co-authored-by: Copilot --- examples/nim_timer/cpp_bindings/main.cpp | 15 +++++++--- examples/nim_timer/cpp_bindings/nimtimer.hpp | 17 +++++++++++ ffi/codegen/cpp.nim | 31 ++++++++++++++++++++ 3 files changed, 59 insertions(+), 4 deletions(-) diff --git a/examples/nim_timer/cpp_bindings/main.cpp b/examples/nim_timer/cpp_bindings/main.cpp index 68e9658..0fd57c0 100644 --- a/examples/nim_timer/cpp_bindings/main.cpp +++ b/examples/nim_timer/cpp_bindings/main.cpp @@ -1,19 +1,24 @@ #include "nimtimer.hpp" #include +#include int main() { try { auto ctx = NimTimerCtx::create(TimerConfig{"cpp-demo"}); std::cout << "[1] Context created\n"; - auto version = ctx.version(); + auto versionFuture = ctx.versionAsync(); + auto echo1Future = ctx.echoAsync(EchoRequest{"hello from C++", 200}); + auto echo2Future = ctx.echoAsync(EchoRequest{"second C++ request", 50}); + + auto version = versionFuture.get(); std::cout << "[2] Version: " << version << "\n"; - auto echo = ctx.echo(EchoRequest{"hello from C++", 200}); + auto echo = echo1Future.get(); std::cout << "[3] Echo 1: echoed=" << echo.echoed << ", timerName=" << echo.timerName << "\n"; - auto echo2 = ctx.echo(EchoRequest{"second C++ request", 50}); + auto echo2 = echo2Future.get(); std::cout << "[4] Echo 2: echoed=" << echo2.echoed << ", timerName=" << echo2.timerName << "\n"; @@ -23,7 +28,9 @@ int main() { std::optional("extra note"), std::optional(3) }; - auto complex = ctx.complex(complexReq); + + auto complexFuture = ctx.complexAsync(complexReq); + auto complex = complexFuture.get(); std::cout << "[5] Complex: summary=" << complex.summary << ", itemCount=" << complex.itemCount << ", hasNote=" << complex.hasNote << "\n"; diff --git a/examples/nim_timer/cpp_bindings/nimtimer.hpp b/examples/nim_timer/cpp_bindings/nimtimer.hpp index a648d84..e38f621 100644 --- a/examples/nim_timer/cpp_bindings/nimtimer.hpp +++ b/examples/nim_timer/cpp_bindings/nimtimer.hpp @@ -5,6 +5,7 @@ #include #include #include +#include #include #include #include @@ -145,6 +146,10 @@ public: return NimTimerCtx(reinterpret_cast(static_cast(addr))); } + static std::future createAsync(const TimerConfig& config) { + return std::async(std::launch::async, [config]() { return create(config); }); + } + EchoResponse echo(const EchoRequest& req) const { const auto req_json = serializeFfiArg(req); const auto raw = ffi_call_([&](FfiCallback cb, void* ud) { @@ -153,6 +158,10 @@ public: return deserializeFfiResult(raw); } + std::future echoAsync(const EchoRequest& req) const { + return std::async(std::launch::async, [this, req]() { return echo(req); }); + } + std::string version() const { const auto raw = ffi_call_([&](FfiCallback cb, void* ud) { return nimtimer_version(ptr_, cb, ud); @@ -160,6 +169,10 @@ public: return deserializeFfiResult(raw); } + std::future versionAsync() const { + return std::async(std::launch::async, [this]() { return version(); }); + } + ComplexResponse complex(const ComplexRequest& req) const { const auto req_json = serializeFfiArg(req); const auto raw = ffi_call_([&](FfiCallback cb, void* ud) { @@ -168,6 +181,10 @@ public: return deserializeFfiResult(raw); } + std::future complexAsync(const ComplexRequest& req) const { + return std::async(std::launch::async, [this, req]() { return complex(req); }); + } + private: void* ptr_; explicit NimTimerCtx(void* p) : ptr_(p) {} diff --git a/ffi/codegen/cpp.nim b/ffi/codegen/cpp.nim index 43b088c..cc23652 100644 --- a/ffi/codegen/cpp.nim +++ b/ffi/codegen/cpp.nim @@ -53,6 +53,7 @@ proc generateCppHeader*( lines.add("#include ") lines.add("#include ") lines.add("#include ") + lines.add("#include ") lines.add("#include ") lines.add("#include ") lines.add("#include ") @@ -238,6 +239,15 @@ proc generateCppHeader*( ) lines.add(" }") lines.add("") + lines.add( + " static std::future<$1> createAsync(const TimerConfig& config) {" % + [ctxTypeName] + ) + lines.add( + " return std::async(std::launch::async, [config]() { return create(config); });" + ) + lines.add(" }") + lines.add("") # Instance methods for m in methods: @@ -245,10 +255,13 @@ proc generateCppHeader*( let retCppType = nimTypeToCpp(m.returnTypeName) var methParams: seq[string] = @[] + var methParamNames: seq[string] = @[] for ep in m.extraParams: let cppType = nimTypeToCpp(ep.typeName) methParams.add("const $1& $2" % [cppType, ep.name]) + methParamNames.add(ep.name) let methParamsStr = methParams.join(", ") + let methParamNamesStr = methParamNames.join(", ") lines.add(" $1 $2($3) const {" % [retCppType, methodName, methParamsStr]) for ep in m.extraParams: @@ -268,6 +281,24 @@ proc generateCppHeader*( lines.add(" return deserializeFfiResult<$1>(raw);" % [retCppType]) lines.add(" }") lines.add("") + if methParamsStr.len > 0: + lines.add( + " std::future<$1> $2Async($3) const {" % + [retCppType, methodName, methParamsStr] + ) + lines.add( + " return std::async(std::launch::async, [this, $1]() { return $2($3); });" % + [methParamNamesStr, methodName, methParamNamesStr] + ) + lines.add(" }") + else: + lines.add(" std::future<$1> $2Async() const {" % [retCppType, methodName]) + lines.add( + " return std::async(std::launch::async, [this]() { return $2(); });" % + [methodName] + ) + lines.add(" }") + lines.add("") lines.add("private:") lines.add(" void* ptr_;")