#ifndef ADAPTERS_OPENCL_CL_KERNEL_COMPLETION_AREQ_H #define ADAPTERS_OPENCL_CL_KERNEL_COMPLETION_AREQ_H #include #include #include #include #define CL_TARGET_OPENCL_VERSION 120 #include #include #include namespace smo { namespace openclBoundary { /** Eager-start std::function callback -> coroutine adapter for OpenCL kernel * completion (cl_int event_command_exec_status posted to io_context). */ template class ClKernelCompletionAReq { public: struct AsyncState { std::atomic settled{false}; cl_int result{}; std::coroutine_handle<> callerSchedHandle; }; explicit ClKernelCompletionAReq( boost::asio::io_context &resumeIoContext, StartFn startFn) : asyncState(std::make_shared()), resumeIoContext(resumeIoContext) { startFn([this](cl_int eventCommandExecStatus) { asyncState->result = eventCommandExecStatus; signalSettledAndResumeCaller(); }); } bool await_ready() const noexcept { return asyncState->settled.load(std::memory_order_acquire); } bool await_suspend(std::coroutine_handle<> callerSchedHandle) noexcept { if (asyncState->settled.load(std::memory_order_acquire)) { return false; } asyncState->callerSchedHandle = callerSchedHandle; return true; } cl_int await_resume() noexcept { return asyncState->result; } private: void signalSettledAndResumeCaller() noexcept { asyncState->settled.store(true, std::memory_order_release); std::coroutine_handle<> handle = asyncState->callerSchedHandle; if (!handle) { return; } boost::asio::post(resumeIoContext, handle); } std::shared_ptr asyncState; boost::asio::io_context &resumeIoContext; }; template ClKernelCompletionAReq getClKernelCompletionAReqAwaiter( boost::asio::io_context &resumeIoContext, StartFn startFn) { return ClKernelCompletionAReq(resumeIoContext, std::move(startFn)); } } // namespace openclBoundary } // namespace smo #endif // ADAPTERS_OPENCL_CL_KERNEL_COMPLETION_AREQ_H