diff --git a/src/libpymcr.cpp b/src/libpymcr.cpp index 6d134cf..db2fee0 100644 --- a/src/libpymcr.cpp +++ b/src/libpymcr.cpp @@ -29,15 +29,21 @@ namespace libpymcr { template T matlab_env::evalloop(matlab::cpplib::FutureResult resAsync) { std::chrono::duration period(1); std::future_status status = resAsync.wait_for(std::chrono::duration(1)); + bool error_already_set = false; while (status != std::future_status::ready) { status = resAsync.wait_for(period); // Prints outputs and errors + py::gil_scoped_acquire gil_acquire; + // Check if there is an interrupt on the Python side (needs GIL) + if (!error_already_set && PyErr_CheckSignals() != 0) { + resAsync.cancel(); + error_already_set = true; + } if(_m_output.get()->in_avail() > 0) { - py::gil_scoped_acquire gil_acquire; py::print(_m_output.get()->str(), py::arg("flush")=true); - py::gil_scoped_release gil_release; _m_output.get()->str(std::basic_string()); } + py::gil_scoped_release gil_release; } return resAsync.get(); } diff --git a/src/matlab_cpp_shared.hpp b/src/matlab_cpp_shared.hpp index 8991c76..143c04b 100644 --- a/src/matlab_cpp_shared.hpp +++ b/src/matlab_cpp_shared.hpp @@ -41,6 +41,7 @@ uintptr_t cppsharedlib_feval_with_completion(const uint64_t matlabHandle, size_t nrhs, void(*success)(void*, size_t, bool, matlab::data::impl::ArrayImpl**), void(*exception)(void*, size_t, bool, size_t, const void*), void* p, void* output, void* error, void(*write)(void*, const char16_t*, size_t), void(*deleter)(void*)); +bool cppsharedlib_cancel_feval_with_completion(uintptr_t taskHandle, bool allowInteruption); namespace { typedef std::basic_streambuf StreamBuffer; @@ -49,6 +50,23 @@ namespace { namespace matlab { + namespace cpplib { + template class FutureResult : public std::future { + public: + FutureResult(std::future&& a_future, uintptr_t a_taskreference) + : future(std::move(a_future)), taskReference(a_taskreference) {}; + T get() { return future.get(); } + template + std::future_status wait_for(const std::chrono::duration& rel_time) const { + return future.wait_for(rel_time); } + bool cancel(bool allowInterrupt = true) { + return cppsharedlib_cancel_feval_with_completion(taskReference, allowInterrupt); } + private: + std::future future; + uintptr_t taskReference; + }; + } + namespace execution { class Exception : public std::exception, public matlab::Exception { @@ -157,7 +175,7 @@ namespace matlab { bool scalar, typename T = typename std::conditional>::type > - std::future _feval(const std::u16string &function, const size_t nlhs, const std::vector &args, + matlab::cpplib::FutureResult _feval(const std::u16string &function, const size_t nlhs, const std::vector &args, const SSBuffer &output = SSBuffer(), const SSBuffer &error = SSBuffer()) { size_t nrhs = args.size(); matlab::data::impl::ArrayImpl** argsImpl = new matlab::data::impl::ArrayImpl*[nrhs]; @@ -170,7 +188,7 @@ namespace matlab { std::string utf8functionname = convertUTF16StringToASCIIString(function); uintptr_t handle = cppsharedlib_feval_with_completion(matlabHandle, utf8functionname.c_str(), nlhs, scalar, argsImpl, nrhs, &_promise_data, &_promise_exception, p, output_, error_, &_write_buffer, &_delete_buffer); - return p->get_future(); + return matlab::cpplib::FutureResult(p->get_future(), handle); } std::vector feval(const std::u16string &function, const size_t nlhs, const std::vector &args, @@ -187,15 +205,15 @@ namespace matlab { std::vector args = {arg}; return _feval(function, 1, args, output, error).get(); } - std::future> fevalAsync(const std::u16string &function, const size_t nlhs, + matlab::cpplib::FutureResult> fevalAsync(const std::u16string &function, const size_t nlhs, const std::vector &args, const SSBuffer &output = SSBuffer(), const SSBuffer &error = SSBuffer()) { return _feval(function, nlhs, args, output, error); } - std::future fevalAsync(const std::u16string &function, const std::vector &args, + matlab::cpplib::FutureResult fevalAsync(const std::u16string &function, const std::vector &args, const SSBuffer &output = SSBuffer(), const SSBuffer &error = SSBuffer()) { return _feval(function, 1, args, output, error); } - std::future fevalAsync(const std::u16string &function, const matlab::data::Array &arg, + matlab::cpplib::FutureResult fevalAsync(const std::u16string &function, const matlab::data::Array &arg, const SSBuffer &output = SSBuffer(), const SSBuffer &error = SSBuffer()) { std::vector args = {arg}; return _feval(function, 1, args, output, error); @@ -209,8 +227,6 @@ namespace matlab { namespace cpplib { - template using FutureResult = std::future; - enum class MATLABApplicationMode { OUT_OF_PROCESS = 0, IN_PROCESS = 1