在C++ coroutines TS (2017)中,有一个等待对象的例子。
template <class Rep, class Period>
auto operator co_await(std::chrono::duration<Rep, Period> d) {
struct awaiter {
std::chrono::system_clock::duration duration;
...
awaiter(std::chrono::system_clock::duration d) : duration(d){}
bool await_ready() const { return duration.count() <= 0; }
void await_resume() {}
void await_suspend(std::experimental::coroutine_handle<> h){...}
};
return awaiter{d};
}
using namespace std::chrono;
my_future<int> h();
my_future<void> g() {
std::cout << "just about go to sleep...\n";
co_await 10ms;
std::cout << "resumed\n";
co_await h();
}
与典型的StackOverflow问题类似,它不会编译。在悄悄地咒骂了一会儿之后,我决定把它变成[MCVE] - 用于学习。下面的代码编译并在VC ++ 17上运行并启用/ await。我认为这可能与TS作者的意图大致相同。唉,它采用了一个独立的线程。很难看出如何通过join
或future::get
或signal_all_at_thread_exit()
或......来收集该帖子。
例如,无法将join添加到awaiter
的析构函数中。在生成的线程中,h.resume()
导致awaiter对象被移动到生成的线程及其(默认)构造函数中。因此析构函数在与构造函数不同的线程中调用。
问题,除了“这是TS的意图吗?”之外,“能以合理经济的方式改进这种悬挂线程吗?” / strong>(如果是这样的话?)
#include <experimental/coroutine>
#include <future>
#include <thread>
namespace xtd = std::experimental;
template <class Rep, class Period>
auto operator co_await(std::chrono::duration<Rep, Period> dur) {
struct awaiter {
using clock = std::chrono::high_resolution_clock;
clock::time_point resume_time;
awaiter(clock::duration dur) : resume_time(clock::now()+dur) {}
bool await_ready() { return resume_time <= clock::now(); }
void await_suspend(xtd::coroutine_handle<> h) {
std::thread([=]() {
std::this_thread::sleep_until(resume_time);
h.resume(); // destructs the obj, which has been std::move()'d
}).detach(); // Detach scares me.
}
void await_resume() {}
};
return awaiter{ dur };
}
using namespace std::chrono;
std::future<int> g() {
co_await 4000ms;
co_return 86;
}
template<typename R>
bool is_ready(std::future<R> const& f)
{ return f.wait_for(std::chrono::seconds(0)) == std::future_status::ready; }
int main() {
using std::cout;
auto gg = g();
cout << "Doing stuff in main, while coroutine is suspended...\n";
std::this_thread::sleep_for(1000ms);
if (!is_ready(gg)) {
cout << "La lala, lala, lala...\n";
std::this_thread::sleep_for(1500ms);
}
cout << "Whew! Done. Getting co_return now...\n";
auto ret = gg.get();
cout << "coroutine resumed and co_returned " << ret << '\n';
system("pause");
return ret;
}
答案 0 :(得分:0)
能以合理的经济方式改善这种倾向吗?
您可以使用“线程池”实现,而不是按需分离线程。
这是玩具示例: https://gist.github.com/yohhoy/a5ec6d4aeeb4c60d3e4f3adfd1df9ebf