diff --git a/async_simple/coro/test/LocalExecutorTest.cpp b/async_simple/coro/test/LocalExecutorTest.cpp new file mode 100644 index 000000000..daa71b859 --- /dev/null +++ b/async_simple/coro/test/LocalExecutorTest.cpp @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2022, Alibaba Group Holding Limited; + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include "async_simple/Try.h" +#include "async_simple/coro/Lazy.h" +#include "async_simple/executors/LocalExecutor.h" + +#include "async_simple/test/unittest.h" + +namespace async_simple { +namespace coro { + +template +struct CallbackAwaiter { +public: + using CallbackFunction = + std::function, std::function)>; + + CallbackAwaiter(CallbackFunction callback_function) + : callback_function_(std::move(callback_function)) {} + + bool await_ready() noexcept { return false; } + + void await_suspend(std::coroutine_handle<> handle) { + callback_function_(handle, [this](T t) { result_ = std::move(t); }); + } + + T await_resume() noexcept { return std::move(result_); } + +private: + CallbackFunction callback_function_; + T result_; +}; + +Lazy async_compute(int i) noexcept { + int ret = co_await CallbackAwaiter{ + [&, i](std::coroutine_handle<> handle, auto set_resume_value) { + set_resume_value(i * 100); + handle.resume(); + }}; + co_return ret; +} + +Lazy coro_compute() { + int sum = 0; + for (auto i = 0; i < 1000; ++i) { + sum += co_await async_compute(i); + } + co_return sum; +} + +TEST(LocalExecutorTest, testStackOverflow) { + executors::LocalExecutor ex; + int result{0}; + coro_compute().via(&ex).start([&](Try i) { result = i.value(); }); + ex.Loop(); + EXPECT_EQ(result, 49950000); +} + +} // namespace coro +} // namespace async_simple diff --git a/async_simple/executors/LocalExecutor.h b/async_simple/executors/LocalExecutor.h new file mode 100644 index 000000000..a4af43a0d --- /dev/null +++ b/async_simple/executors/LocalExecutor.h @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2022, Alibaba Group Holding Limited; + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ASYNC_LOCAL_EXECUTOR_H +#define ASYNC_LOCAL_EXECUTOR_H + +#include +#include "async_simple/Executor.h" + +namespace async_simple { + +namespace executors { + +class LocalExecutor : public Executor { +public: + LocalExecutor() : Executor("local executor") {} + + bool schedule(Func func) override { + ready_queue_.push_back(std::move(func)); + return true; + } + + void Loop() { + while (true) { + if (ready_queue_.empty()) { + return; + } + Func func = std::move(ready_queue_.front()); + ready_queue_.pop_front(); + func(); + } + } + +private: + std::deque ready_queue_; +}; + +} // namespace executors + +} // namespace async_simple + +#endif diff --git a/bazel/config/copt.bzl b/bazel/config/copt.bzl index 05db74b00..d07fdc6a1 100644 --- a/bazel/config/copt.bzl +++ b/bazel/config/copt.bzl @@ -1,5 +1,5 @@ ASYNC_SIMPLE_COPTS = select({ - "@com_github_async_simple//bazel/config:msvc_compiler": [ + "@async_simple//bazel/config:msvc_compiler": [ "/std:c++20", "/await:strict", "/EHa"