Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Deprecated setEx, instead by start(cb, ex) #400

Merged
merged 2 commits into from
Nov 7, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 14 additions & 3 deletions async_simple/coro/Lazy.h
Original file line number Diff line number Diff line change
Expand Up @@ -507,16 +507,25 @@ class [[nodiscard]] CORO_ONLY_DESTROY_WHEN_DONE ELIDEABLE_AFTER_AWAIT Lazy

// Bind an executor only. Don't re-schedule.
//
// Users shouldn't use `setEx` directly. `setEx` is designed
// for internal purpose only. See uthread/Await.h/await for details.
Lazy<T> setEx(Executor* ex) && {
// This function is deprecated, please use start(cb,ex) instead of setEx.
[[deprecated]] Lazy<T> setEx(Executor* ex) && {
logicAssert(this->_coro.operator bool(),
"Lazy do not have a coroutine_handle "
"Maybe the allocation failed or you're using a used Lazy");
this->_coro.promise()._executor = ex;
return Lazy<T>(std::exchange(this->_coro, nullptr));
}

using Base::start;

// Bind an executor and start coroutine without scheduling immediately.
template <typename F>
void directlyStart(F&& callback, Executor* executor) requires(
std::is_invocable_v<F&&, Try<T>>) {
this->_coro.promise()._executor = executor;
return start(std::forward<F>(callback));
}

auto coAwait(Executor* ex) {
logicAssert(this->_coro.operator bool(),
"Lazy do not have a coroutine_handle "
Expand All @@ -531,6 +540,8 @@ class [[nodiscard]] CORO_ONLY_DESTROY_WHEN_DONE ELIDEABLE_AFTER_AWAIT Lazy
friend class RescheduleLazy<T>;
};

// dispatch a lazy to executor, dont reschedule immediately

// A RescheduleLazy is a Lazy with an executor. The executor of a RescheduleLazy
// wouldn't/shouldn't be nullptr. So we needn't check it.
//
Expand Down
17 changes: 17 additions & 0 deletions async_simple/coro/test/LazyTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,15 +17,18 @@
#include <condition_variable>
#include <exception>
#include <functional>
#include <future>
#include <mutex>
#include <thread>
#include <type_traits>

#include <iostream>

#include <chrono>
#include "async_simple/Executor.h"
#include "async_simple/coro/Collect.h"
#include "async_simple/coro/Lazy.h"
#include "async_simple/coro/Sleep.h"
#include "async_simple/coro/SyncAwait.h"
#include "async_simple/coro/test/Time.h"
#include "async_simple/executors/SimpleExecutor.h"
Expand Down Expand Up @@ -256,6 +259,20 @@ TEST_F(LazyTest, testSimpleAsync2) {
ASSERT_EQ(101, syncAwait(test(), &_executor));
}

TEST_F(LazyTest, testStartWithExecutor) {
auto test = [this]() -> Lazy<void> {
auto executor = co_await CurrentExecutor();
EXPECT_TRUE(executor == &_executor);
EXPECT_TRUE(executor->currentThreadInExecutor() == false);
co_await async_simple::coro::sleep(10ms);
CHECK_EXECUTOR(&_executor);
co_return;
};
std::promise<void> f;
test().directlyStart([&f](auto&&) { f.set_value(); }, &_executor);
f.get_future().wait();
}

TEST_F(LazyTest, testVia) {
auto test = [this]() -> Lazy<int> {
auto tid = std::this_thread::get_id();
Expand Down
3 changes: 1 addition & 2 deletions async_simple/uthread/Await.h
Original file line number Diff line number Diff line change
Expand Up @@ -98,8 +98,7 @@ decltype(auto) await(Executor* ex, Fn&& fn, Args&&... args) requires
co_return;
};
lazy(std::forward<Fn>(fn), std::forward<Args>(args)...)
.setEx(ex)
.start([](auto&&) {});
.directlyStart([](auto&&) {}, ex);
return await(std::move(f));
}

Expand Down
8 changes: 5 additions & 3 deletions docs/docs.cn/Executor.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,16 @@ Executor是调度协程的关键组件。绝大多数开源协程框架提供内

## 使用Executor

让协程运行在指定的调度器中非常简单,只需要创建协程时传递Executor给协程即可。在Lazy中通过`via()/setEx()`可以传递Executor;在Uthread中设置`async()`的Executor参数传递。
让协程运行在指定的调度器中非常简单,只需要创建协程时传递Executor给协程即可。在Lazy中通过`via()`可以传递Executor。或者可以使用`directlyStart(callback, executor)`接口启动协程并惰性调度,也可以在Uthread中设置`async()`的Executor参数传递。

```cpp
Executor e;

// lazy
co_await f().via(&e).start([](){});
co_await f().setEx(&e);
// 协程绑定在对应的调度器上,立即调度执行
f().via(&e).start([](auto&&){});
// 协程绑定在对应的调度器上,延迟调度执行
f().start([](auto&&){},&e);

// uthread
uthread::async<uthread::Launch::Schedule>(<lambda>, &e);
Expand Down
24 changes: 23 additions & 1 deletion docs/docs.cn/Lazy.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ Lazy<int> task2(int x) {

## 启动方式

一个 Lazy 应该以 `co_await`、 `syncAwait` 以及 `.start(callback)` 方式启动。
一个 Lazy 应该以 `co_await`、 `syncAwait`, `.start(callback)` 以及 `directlyStart(callback, executor)`方式启动。

### co_await 启动

Expand Down Expand Up @@ -93,6 +93,28 @@ void func() {
task().start([](auto&&){});
```

### directlyStart(callback, executor) 启动

和`start`类似,但是提供了调度器接口,用于在启动协程时绑定调度器。需要注意的是,`directlyStart`不会在启动时立即调度协程。

```cpp
Lazy<> task() {

auto e = co_await currentExecutor{};
// 已经成功绑定调度器
assert(e!=nullptr);
// 惰性调度,此时任务还未被提交给调度器运行
assert(e.currentThreadInExecutor()==false);
co_await coro::Sleep(1s);
// Sleep函数需要使用调度器,因此任务已被提交给调度器运行。
assert(e.currentThreadInExecutor()==true);
}
void func() {
auto executor=std::make_shared<executors::SimpleExecutor>(1);
task().directlyStart([executor](Try<void> Result){},executor.get());
}
```

### syncAwait 启动

例如:
Expand Down
8 changes: 5 additions & 3 deletions docs/docs.en/Executor.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,16 @@ Executor is the key component for shceduling coroutine. A lot of the open-source

### Use Executor

It is easy to assign a coroutine instance to an executor. The user need to pass the executor to coroutine only. The users could assign an executor to a Lazy by `via/setEx`. They could use `async` to pass Executor to Uthread.
It is easy to assign a coroutine instance to an executor. The user need to pass the executor to coroutine only. The users could assign an executor to a Lazy then schedule immediately by `via`. User could also use `directlyStart(callback, executor)` to assign an executor wihtout schedul immediately. They could use `async` to pass Executor to Uthread.

```cpp
Executor e;

// lazy
co_await f().via(&e).start([](){});
co_await f().setEx(&e);
// schedule to executor immediately
f().via(&e).start([](auto&&){});
// binding executor but dont schedule immediately
f().start([](auto&&){},&e);

// uthread
uthread::async<uthread::Launch::Schedule>(<lambda>, &e);
Expand Down
24 changes: 23 additions & 1 deletion docs/docs.en/Lazy.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ of async_simple itself, we requrie the alignment of `T` in `Lazy<T>` can exceed

## Start Lazy

We could start a Lazy by `co_await`, `syncAwait` and `.start(callback)`.
We could start a Lazy by `co_await`, `syncAwait`, `.start(callback)` or `directlyStart(callback, executor)`.

### co_await

Expand Down Expand Up @@ -93,6 +93,28 @@ In case the `callback` isn't needed, we could write:
task().start([](auto&&){});
```


### directlyStart(callback, executor)

Similar to `start`, but provides a paramter for binding a scheduler when starting a coroutine. It is important to note that `directlyStart` does not immediately schedule the task when coroutine start.

```cpp
Lazy<> task() {
auto e = co_await currentExecutor{};
// binding executor successfully.
assert(e!=nullptr);
// lazy schedule, work doesn't run in executor.
assert(e->currentThreadInExecutor()==false);
co_await coro::Sleep(1s);
// Sleep function need executor schedule, now work runs in executor.
assert(e->currentThreadInExecutor()==true);
}
void func() {
auto executor=std::make_shared<executors::SimpleExecutor>(1);
task().directlyStart([executor](Try<void> Result){},executor.get());
}
```

### syncAwait

For example:
Expand Down
1 change: 1 addition & 0 deletions modules_test/_deps/googletest-src
Submodule googletest-src added at e2239e
Loading