diff --git a/src/c_wrapper/error.h b/src/c_wrapper/error.h index e5d4f67338701714deb5d4e7e7d575829bfd4084..5e3508df5fb31c9440cfa30d2d3b392f3c9cc908 100644 --- a/src/c_wrapper/error.h +++ b/src/c_wrapper/error.h @@ -237,6 +237,14 @@ call_guarded(T (*func)(ArgTypes...), const char *name, ArgTypes2&&... args) #define pyopencl_call_guarded(func, args...) \ pyopencl::call_guarded(func, #func, args) +static PYOPENCL_INLINE void +cleanup_print_error(cl_int status_code, const char *name) noexcept +{ + std::cerr << ("PyOpenCL WARNING: a clean-up operation failed " + "(dead context maybe?)") << std::endl + << name << " failed with code " << status_code << std::endl; +} + template static PYOPENCL_INLINE void call_guarded_cleanup(cl_int (*func)(ArgTypes...), const char *name, @@ -245,10 +253,7 @@ call_guarded_cleanup(cl_int (*func)(ArgTypes...), const char *name, auto argpack = make_clargpack(std::forward(args)...); cl_int status_code = argpack.clcall(func, name); if (status_code != CL_SUCCESS) { - std::cerr - << ("PyOpenCL WARNING: a clean-up operation failed " - "(dead context maybe?)") << std::endl - << name << " failed with code " << status_code << std::endl; + cleanup_print_error(status_code, name); } else { argpack.finish(); } diff --git a/src/c_wrapper/event.cpp b/src/c_wrapper/event.cpp index 7dd2c3d76273c451a2935ab67153b95820b99abe..bd1f14c805f85e1b8c263810555d8f5ed41fdf43 100644 --- a/src/c_wrapper/event.cpp +++ b/src/c_wrapper/event.cpp @@ -15,10 +15,11 @@ template void print_buf(std::ostream&, const cl_event*, class event_private { mutable volatile std::atomic_bool m_finished; - virtual void - finish() noexcept - {} + virtual void finish() noexcept = 0; public: + event_private() + : m_finished(false) + {} virtual ~event_private() {} @@ -43,52 +44,64 @@ event::event(cl_event event, bool retain, event_private *p) try { pyopencl_call_guarded(clRetainEvent, this); } catch (...) { + m_p->call_finish(); delete m_p; throw; } } } -void +bool event::release_private() noexcept { if (!m_p) - return; + return true; if (m_p->is_finished()) { delete m_p; - return; + return true; } #if PYOPENCL_CL_VERSION >= 0x1010 - if (support_cb) { + cl_int status = 0; + try { + pyopencl_call_guarded(clGetEventInfo, this, + CL_EVENT_COMMAND_EXECUTION_STATUS, + size_arg(status), nullptr); + } catch (const clerror &e) { + cleanup_print_error(e.code(), e.what()); + m_p->call_finish(); + delete m_p; + return true; + } + // Event Callback may not be run immediately when the event is already + // completed. + if (support_cb && status > CL_COMPLETE) { try { event_private *p = m_p; set_callback(CL_COMPLETE, [p] (cl_int) { - p->call_finish(); - delete p; - }); + p->call_finish(); + delete p; + }); + return true; } catch (const clerror &e) { - std::cerr - << ("PyOpenCL WARNING: a clean-up operation failed " - "(dead context maybe?)") << std::endl - << e.what() << " failed with code " << e.code() << std::endl; + cleanup_print_error(e.code(), e.what()); } - } else { -#endif - std::thread t([] (cl_event evt, event_private *p) { - pyopencl_call_guarded_cleanup(clWaitForEvents, len_arg(evt)); - p->call_finish(); - delete p; - }, data(), m_p); - t.detach(); -#if PYOPENCL_CL_VERSION >= 0x1010 } #endif + std::thread t([] (cl_event evt, event_private *p) { + pyopencl_call_guarded_cleanup(clWaitForEvents, len_arg(evt)); + p->call_finish(); + pyopencl_call_guarded_cleanup(clReleaseEvent, evt); + delete p; + }, data(), m_p); + t.detach(); + return false; } event::~event() { - release_private(); - pyopencl_call_guarded_cleanup(clReleaseEvent, this); + if (release_private()) { + pyopencl_call_guarded_cleanup(clReleaseEvent, this); + } } generic_info @@ -139,14 +152,12 @@ event::wait() const class nanny_event_private : public event_private { void *m_ward; - void finished() noexcept + void finish() noexcept { void *ward = m_ward; m_ward = nullptr; py::deref(ward); } - ~nanny_event_private() - {} public: nanny_event_private(void *ward) : m_ward(nullptr) diff --git a/src/c_wrapper/event.h b/src/c_wrapper/event.h index 2e90c0e8a162ff7f972372f463299a104a2e9274..27ba85dca8454e4079d3ed39ccfe0575b60da397 100644 --- a/src/c_wrapper/event.h +++ b/src/c_wrapper/event.h @@ -17,7 +17,8 @@ class event_private; class event : public clobj { event_private *m_p; - void release_private() noexcept; + // return whether the event need to be released. + PYOPENCL_USE_RESULT bool release_private() noexcept; protected: PYOPENCL_INLINE event_private* get_p() const