From c24595af451039078dfa5b02a49038cd27e7cad7 Mon Sep 17 00:00:00 2001 From: Johan Mabille Date: Wed, 20 Mar 2024 09:56:36 +0100 Subject: [PATCH] Implemented asynchronous execute_request --- .../source/example/src/custom_interpreter.cpp | 16 ++++---- .../source/example/src/custom_interpreter.hpp | 13 +++---- docs/source/kernel_implementation.rst | 2 +- include/xeus/xinterpreter.hpp | 32 ++++++++------- src/xinterpreter.cpp | 27 +++++++------ src/xkernel_core.cpp | 39 +++++++++++++------ src/xmock_interpreter.hpp | 15 ++++--- test/xmock_interpreter.cpp | 17 ++++---- test/xmock_interpreter.hpp | 13 +++---- 9 files changed, 95 insertions(+), 79 deletions(-) diff --git a/docs/source/example/src/custom_interpreter.cpp b/docs/source/example/src/custom_interpreter.cpp index dba03b01..d67d992a 100644 --- a/docs/source/example/src/custom_interpreter.cpp +++ b/docs/source/example/src/custom_interpreter.cpp @@ -19,13 +19,12 @@ namespace nl = nlohmann; namespace custom { - nl::json custom_interpreter::execute_request_impl(xrequest_context request_context, // data required by other functions - int execution_counter, // Typically the cell number - const std::string& /*code*/, // Code to execute - bool /*silent*/, - bool /*store_history*/, - nl::json /*user_expressions*/, - bool /*allow_stdin*/) + void custom_interpreter::execute_request_impl(xrequest_context request_context, + send_reply_callback cb, + int execution_counter, + const std::string& code, + execute_request_config config, + nl::json user_expressions) { // You can use the C-API of your target language for executing the code, // e.g. `PyRun_String` for the Python C-API @@ -45,7 +44,8 @@ namespace custom // publish_execution_error(error_name, error_value, error_traceback); publish_execution_error(request_context, "TypeError", "123", {"!@#$", "*(*"}); - return xeus::create_successful_reply(); + // Call the callback parameter to send the reply + cb(xeus::create_successful_reply()); } void custom_interpreter::configure_impl() diff --git a/docs/source/example/src/custom_interpreter.hpp b/docs/source/example/src/custom_interpreter.hpp index 1c89db41..12a00861 100644 --- a/docs/source/example/src/custom_interpreter.hpp +++ b/docs/source/example/src/custom_interpreter.hpp @@ -31,13 +31,12 @@ namespace custom void configure_impl() override; - nl::json execute_request_impl(xrequest_context request_context, - int execution_counter, - const std::string& code, - bool silent, - bool store_history, - nl::json user_expressions, - bool allow_stdin) override; + void execute_request_impl(xrequest_context request_context, + send_reply_callback cb, + int execution_counter, + const std::string& code, + execute_request_config config, + nl::json user_expressions) override; nl::json complete_request_impl(const std::string& code, int cursor_pos) override; diff --git a/docs/source/kernel_implementation.rst b/docs/source/kernel_implementation.rst index b8e8320a..46a289f1 100644 --- a/docs/source/kernel_implementation.rst +++ b/docs/source/kernel_implementation.rst @@ -51,7 +51,7 @@ course the ``execute_request_impl`` which executes the code whenever the client .. literalinclude:: ./example/src/custom_interpreter.cpp :language: cpp :dedent: 4 - :lines: 22-48 + :lines: 22-49 The result and arguments of the execution request are described in the execute_request_ documentation. diff --git a/include/xeus/xinterpreter.hpp b/include/xeus/xinterpreter.hpp index 41847ce8..6a8e0fc2 100644 --- a/include/xeus/xinterpreter.hpp +++ b/include/xeus/xinterpreter.hpp @@ -27,6 +27,13 @@ namespace xeus XEUS_API bool register_interpreter(xinterpreter* interpreter); XEUS_API xinterpreter& get_interpreter(); + struct XEUS_API execute_request_config + { + bool silent; + bool store_history; + bool allow_stdin; + }; + class XEUS_API xinterpreter { public: @@ -42,12 +49,12 @@ namespace xeus void configure(); - nl::json execute_request(xrequest_context context, - const std::string& code, - bool silent, - bool store_history, - nl::json user_expressions, - bool allow_stdin); + using send_reply_callback = std::function; + void execute_request(xrequest_context context, + send_reply_callback callback, + const std::string& code, + execute_request_config config, + nl::json user_expressions); nl::json complete_request(const std::string& code, int cursor_pos); @@ -101,13 +108,12 @@ namespace xeus virtual void configure_impl() = 0; - virtual nl::json execute_request_impl(xrequest_context request_context, - int execution_counter, - const std::string& code, - bool silent, - bool store_history, - nl::json user_expressions, - bool allow_stdin) = 0; + virtual void execute_request_impl(xrequest_context request_context, + send_reply_callback cb, + int execution_counter, + const std::string& code, + execute_request_config config, + nl::json user_expressions) = 0; virtual nl::json complete_request_impl(const std::string& code, int cursor_pos) = 0; diff --git a/src/xinterpreter.cpp b/src/xinterpreter.cpp index 536dce12..f6c9c839 100644 --- a/src/xinterpreter.cpp +++ b/src/xinterpreter.cpp @@ -29,27 +29,26 @@ namespace xeus configure_impl(); } - nl::json xinterpreter::execute_request(xrequest_context context, - const std::string& code, - bool silent, - bool store_history, - nl::json user_expressions, - bool allow_stdin) - { - if (!silent) + void xinterpreter::execute_request(xrequest_context context, + send_reply_callback callback, + const std::string& code, + execute_request_config config, + nl::json user_expressions) + { + if (!config.silent) { ++m_execution_count; publish_execution_input(context, code, m_execution_count); } - nl::json reply = execute_request_impl( + execute_request_impl( std::move(context), - m_execution_count, code, silent, - store_history, user_expressions, allow_stdin + std::move(callback), + m_execution_count, + code, + std::move(config), + user_expressions ); - - reply["execution_count"] = m_execution_count; - return reply; } nl::json xinterpreter::complete_request(const std::string& code, int cursor_pos) diff --git a/src/xkernel_core.cpp b/src/xkernel_core.cpp index 98ac5a20..54ed9287 100644 --- a/src/xkernel_core.cpp +++ b/src/xkernel_core.cpp @@ -236,19 +236,34 @@ namespace xeus bool allow_stdin = content.value("allow_stdin", true); bool stop_on_error = content.value("stop_on_error", false); - nl::json metadata = get_metadata(); xrequest_context request_context(request.header(), c, request.identities()); - nl::json reply = p_interpreter->execute_request(std::move(request_context), - code, silent, store_history, std::move(user_expression), allow_stdin); - int execution_count = reply.value("execution_count", 1); - std::string status = reply.value("status", "error"); - send_reply( - request.identities(), - "execute_reply", - request.header(), - std::move(metadata), - std::move(reply), - c); + execute_request_config config { silent, store_history, allow_stdin }; + int execution_count = 1; + std::string status; + auto reply_callback = [&](nl::json reply) + { + execution_count = reply.value("execution_count", 1); + status = reply.value("status", "error"); + nl::json metadata = get_metadata(); + + send_reply( + request.identities(), + "execute_reply", + request.header(), + std::move(metadata), + std::move(reply), + c + ); + }; + + p_interpreter->execute_request( + std::move(request_context), + std::move(reply_callback), + code, + config, + std::move(user_expression) + ); + if (!silent && store_history) { diff --git a/src/xmock_interpreter.hpp b/src/xmock_interpreter.hpp index 5ef465c3..375d829f 100644 --- a/src/xmock_interpreter.hpp +++ b/src/xmock_interpreter.hpp @@ -38,15 +38,14 @@ namespace xeus { } - nl::json execute_request_impl(xrequest_context /*request_context*/, - int /*execution_counter*/, - const std::string& /*code*/, - bool /*silent*/, - bool /*store_history*/, - nl::json /*user_expressions*/, - bool /*allow_stdin*/) override + void execute_request_impl(xrequest_context /*request_context*/, + send_reply_callback cb, + int /*execution_counter*/, + const std::string& /*code*/, + execute_request_config /*config*/, + nl::json /*user_expressions*/) override { - return nl::json(); + cb(nl::json()); } nl::json complete_request_impl(const std::string& /*code*/, int /*cursor_pos*/) override diff --git a/test/xmock_interpreter.cpp b/test/xmock_interpreter.cpp index f498db49..204ba539 100644 --- a/test/xmock_interpreter.cpp +++ b/test/xmock_interpreter.cpp @@ -29,13 +29,12 @@ namespace xeus using function_type = std::function; } - nl::json xmock_interpreter::execute_request_impl(xrequest_context request_context, - int execution_counter, - const std::string& code, - bool /* silent */, - bool /* store_history */, - nl::json /* user_expressions */, - bool /* allow_stdin */) + void xmock_interpreter::execute_request_impl(xrequest_context request_context, + send_reply_callback cb, + int execution_counter, + const std::string& code, + execute_request_config /*config*/, + nl::json /*user_expressions*/) { if (code.compare("hello, world") == 0) { @@ -62,14 +61,14 @@ namespace xeus {"start", 0} }); - return xeus::create_successful_reply(payload); + cb(xeus::create_successful_reply(payload)); } nl::json pub_data; pub_data["text/plain"] = code; publish_execution_result(request_context, execution_counter, std::move(pub_data), nl::json::object()); - return xeus::create_successful_reply(); + cb(xeus::create_successful_reply()); } nl::json xmock_interpreter::complete_request_impl(const std::string& /* code */, diff --git a/test/xmock_interpreter.hpp b/test/xmock_interpreter.hpp index 2ec010c7..46c7c2c9 100644 --- a/test/xmock_interpreter.hpp +++ b/test/xmock_interpreter.hpp @@ -25,13 +25,12 @@ namespace xeus void configure_impl() override; - nl::json execute_request_impl(xrequest_context request_context, - int execution_counter, - const std::string& code, - bool silent, - bool store_history, - nl::json user_expressions, - bool allow_stdin) override; + void execute_request_impl(xrequest_context request_context, + send_reply_callback cb, + int execution_counter, + const std::string& code, + execute_request_config config, + nl::json user_expressions) override; nl::json complete_request_impl(const std::string& code, int cursor_pos) override;