diff --git a/README.md b/README.md index bf3487e..be38cf1 100644 --- a/README.md +++ b/README.md @@ -123,12 +123,12 @@ awaitable some_work_with_sleep() } ``` -async_qtimer_shot 只要使用 executor_awaitable 对 QTimer::singleShot 进行一次小小的封装就可以了。 +async_qtimer_shot 只要使用 callback_awaitable 对 QTimer::singleShot 进行一次小小的封装就可以了。 ```cpp awaitable async_qtimer_shot(int ms) { - co_await executor_awaitable([ms](auto continuation) { + co_await callback_awaitable([ms](auto continuation) { QTimer::singleShot(ms, [continuation = std::move(continuation)]() mutable { continuation(); @@ -141,7 +141,7 @@ awaitable async_qtimer_shot(int ms) 可见这种封装是非常容易的。 -如果需要 处理有返回值的回调,则只需要把 executor_awaitable 里的 void 替换为相应的类型即可。 +如果需要 处理有返回值的回调,则只需要把 `callback_awaitable` 里的 void 替换为相应的类型即可。 例如为 QTcpSocket 封装为异步读取: @@ -150,7 +150,7 @@ awaitable async_read_qsocket(QTcpSocket* s, void* buffer, int buffer_size) { QObject* context = new QObject{s}; - auto read_size = co_await executor_awaitable([&context, s, buffer, buffers_size](auto continuation) + auto read_size = co_await callback_awaitable([&context, s, buffer, buffers_size](auto continuation) { QObject::connect(s, &QIODevice::readyRead, context, [s, &context, buffer, buffers_size]() mutable diff --git a/include/ucoro/awaitable.hpp b/include/ucoro/awaitable.hpp index b7f142c..564faa2 100644 --- a/include/ucoro/awaitable.hpp +++ b/include/ucoro/awaitable.hpp @@ -602,42 +602,6 @@ namespace ucoro CallbackFunction callback_function_; }; - ////////////////////////////////////////////////////////////////////////// - - template - struct ExecutorAwaiter : public CallbackAwaiterBase - { - public: - explicit ExecutorAwaiter(CallbackFunction&& callback_function) - : callback_function_(std::move(callback_function)) - { - } - - constexpr bool await_ready() noexcept - { - return false; - } - - void await_suspend(std::coroutine_handle<> handle) - { - if constexpr (std::is_void_v) - { - callback_function_(handle); - } - else - { - callback_function_([handle = std::move(handle), this](T t) mutable - { - this->result_ = std::move(t); - handle.resume(); - }); - } - } - - private: - CallbackFunction callback_function_; - }; - } // namespace ucoro ////////////////////////////////////////////////////////////////////////// @@ -648,12 +612,6 @@ ucoro::CallbackAwaiter callback_awaitable(callback&& cb) return ucoro::CallbackAwaiter{std::forward(cb)}; } -template -ucoro::ExecutorAwaiter executor_awaitable(callback&& cb) -{ - return ucoro::ExecutorAwaiter{std::forward(cb)}; -} - template auto coro_start(Awaitable&& coro, Local&& local) { diff --git a/tests/test3/test.cpp b/tests/test3/test.cpp index 07b4bd6..82bbb4c 100644 --- a/tests/test3/test.cpp +++ b/tests/test3/test.cpp @@ -5,16 +5,10 @@ int main(int argc, char **argv) { using CallbackAwaiterType0 = ucoro::CallbackAwaiter; - using ExecutorAwaiterType0 = ucoro::ExecutorAwaiter ; - using CallbackAwaiterType1 = ucoro::CallbackAwaiter ; - using ExecutorAwaiterType1 = ucoro::ExecutorAwaiter ; static_assert(ucoro::detail::is_awaiter_v < CallbackAwaiterType0 >, "not a coroutine"); - static_assert(ucoro::detail::is_awaiter_v < ExecutorAwaiterType0 >, "not a coroutine"); - static_assert(ucoro::detail::is_awaiter_v < CallbackAwaiterType1 >, "not a coroutine"); - static_assert(ucoro::detail::is_awaiter_v < ExecutorAwaiterType1 >, "not a coroutine"); static_assert(ucoro::detail::is_awaiter_v < ucoro::awaitable >, "not a coroutine"); static_assert(ucoro::detail::is_awaiter_v < ucoro::awaitable >, "not a coroutine"); diff --git a/tests/test_curl/test_curl.cpp b/tests/test_curl/test_curl.cpp index 5da9f6f..6989310 100644 --- a/tests/test_curl/test_curl.cpp +++ b/tests/test_curl/test_curl.cpp @@ -5,17 +5,53 @@ #include "curl/curl.h" +struct completion_job_data +{ + static void do_completion_job(void* completion_data) + { + (*reinterpret_cast(completion_data))(); + delete reinterpret_cast(completion_data); + } + + virtual ~completion_job_data() + { + } + + virtual void operator() () + { + } +}; + + +template +struct completion_job_data_for_coro : public completion_job_data +{ + continuation_t continuation; + + completion_job_data_for_coro(continuation_t&& continuation) + : continuation(continuation) + { + } + + virtual void operator() () override + { + continuation(); + } +}; + ucoro::awaitable async_curl_http_post(std::string url) { - CURLM *curl = co_await ucoro::local_storage_t{}; + CURLM* curl = co_await ucoro::local_storage_t{}; - co_await executor_awaitable([curl, url](std::coroutine_handle continuation) + co_await callback_awaitable([curl, url](auto continuation) { auto http_handle = curl_easy_init(); + auto complete_op = new completion_job_data_for_coro(std::move(continuation)); + /* set the options (I left out a few, you get the point anyway) */ curl_easy_setopt(http_handle, CURLOPT_URL, url.c_str()); - curl_easy_setopt(http_handle, CURLOPT_PRIVATE, continuation.address()); + curl_easy_setopt(http_handle, CURLOPT_PRIVATE, complete_op); curl_multi_add_handle(curl, http_handle); curl_multi_wakeup(curl); @@ -57,7 +93,7 @@ ucoro::awaitable coro_compute() global_exit_loop = true; } -int main(int argc, char **argv) +int main(int argc, char** argv) { curl_global_init(CURL_GLOBAL_ALL); auto curl = curl_multi_init(); @@ -70,9 +106,9 @@ int main(int argc, char **argv) // 注意这里,执行到这里的时候,上诉 NOTE 里的 2号位代码执行完毕,return 了。1号位的代码,尚未执行到。 int msgs_left = -1; - CURLMsg *msg; + CURLMsg* msg; - for(;;) + for (;;) { int still_alive = 1; curl_multi_perform(curl, &still_alive); @@ -82,14 +118,13 @@ int main(int argc, char **argv) { if (msg->msg == CURLMSG_DONE) { - CURL *e = msg->easy_handle; + CURL* e = msg->easy_handle; fprintf(stderr, "R: %d - %s\n", msg->data.result, curl_easy_strerror(msg->data.result)); - void * coroutine_handle_address = nullptr; - curl_easy_getinfo(e, CURLINFO_PRIVATE, &coroutine_handle_address); - if (coroutine_handle_address) + void* completion_job_data = nullptr; + curl_easy_getinfo(e, CURLINFO_PRIVATE, &completion_job_data); + if (completion_job_data) { - auto completion_handle = std::coroutine_handle::from_address(coroutine_handle_address); - completion_handle(); + completion_job_data::do_completion_job(completion_job_data); } curl_multi_remove_handle(curl, e); @@ -102,7 +137,9 @@ int main(int argc, char **argv) } if (global_exit_loop) + { break; + } curl_multi_wait(curl, NULL, 0, 1000, NULL); } diff --git a/tests/testlibevent/test.cpp b/tests/testlibevent/test.cpp index 97614fe..9ef8b99 100644 --- a/tests/testlibevent/test.cpp +++ b/tests/testlibevent/test.cpp @@ -3,23 +3,48 @@ #include "event2/event.h" +template +struct completion_job_data_for_coro +{ + continuation_t continuation_; + + event * ev_; + + completion_job_data_for_coro(continuation_t&& continuation) + : continuation_(continuation) + , ev_(nullptr) + { + } + + void operator() () + { + continuation_(); + event_free(ev_); + } +}; + ucoro::awaitable async_sleep_with_event_timer(int ms) { event_base* io = co_await ucoro::local_storage_t(); - co_await executor_awaitable([ms, io](auto continuation) + co_await callback_awaitable([ms, io](auto continuation) { timeval tout = { .tv_sec = ms / 1000, .tv_usec = 1000 * (ms % 1000) }; - auto ev = event_new(io, -1, 0, [](evutil_socket_t, short, void * continuation_address) + auto complete_op = new completion_job_data_for_coro(std::move(continuation)); + + auto ev = event_new(io, -1, 0, [](evutil_socket_t, short, void * user_data) { - auto continuation_ = std::coroutine_handle<>::from_address(continuation_address); - continuation_.resume(); - }, continuation.address()); + auto complete_op = reinterpret_cast*>(user_data); + (*complete_op)(); + delete complete_op; + + }, complete_op); + complete_op->ev_ = ev; event_add(ev, &tout); }); }