Обновлено
Segmentation fault
было вызвано попыткой .get()
на недопустимом std::future
. Однако сопрограммы еще не совсем работают.
[ 1010 * godbolt *]
[ wandbox ]
У меня есть такой тип ожидания:
template<typename T>
struct awaitable
{
awaitable() = default;
awaitable(awaitable&& other) : val(std::move(other.val) ) { }
awaitable(std::future<T>&& other_f) : val(std::move(other_f ) ) { }
bool await_ready() { return true; }
void await_suspend(std::experimental::coroutine_handle<> h) { h.resume(); }
T await_resume() { return val.get(); }
private:
std::future<T> val;
};
специализировать тип обещания coroutine_traits, как это
template<typename T, typename ...Args>
struct std::experimental::coroutine_traits<awaitable<T>, Args...>
{
struct promise_type {
suspend_never initial_suspend() { return {}; }
suspend_never final_suspend() { return {}; }
void unhandled_exception() { std::terminate(); }
awaitable<T> get_return_object() { return std::move(f); }
T return_value(T r) {
if constexpr (_DEBUG) std::cout << "About to return_value(" << r << ')' << std::endl;
return r; }
private:
awaitable<T> f;
};
};
есть несколько ожидающих
awaitable<int> async_add(int a, int b) {
auto fut = std::async([=]() {
int c = a + b;
return c;
});
return std::move(fut);
}
awaitable<int> async_fib(int n)
{
if (n <= 2)
co_return 1;
int a = 1, b = 1;
// iterate computing fib(n)
for (int i = 0; i < n - 2; ++i)
{
int c = co_await async_add(a, b);
if constexpr (_DEBUG) {
std::cout <<
"After co_await async_add(" << std::setw(3) << a <<
"," << std::setw(3) << b << ")\t"
"i = " << i << "\t"
"c = " << c << "\t"
"[ fib(" << i + 3 << ") ]" << std::endl;
}
a = b;
b = c;
}
co_return b;
}
Когда я пытался получить значение:
int main()
{
std::string str;
std::getline(std::cin, str);
awaitable<int> continua_v = async_fib(std::stoi(str) );
if constexpr (_DEBUG) std::cout << "About to retrieve value..." << std::endl;
int result = continua_v.await_resume();
if constexpr (_DEBUG) std::cout << "Retrieving has succeeded : " << result << std::endl;
return result;
}
Произошла ошибка сегментации
Start
After co_await async_add( 1, 1) i = 0 c = 2 [ fib(3) ]
After co_await async_add( 1, 2) i = 1 c = 3 [ fib(4) ]
After co_await async_add( 2, 3) i = 2 c = 5 [ fib(5) ]
After co_await async_add( 3, 5) i = 3 c = 8 [ fib(6) ]
After co_await async_add( 5, 8) i = 4 c = 13 [ fib(7) ]
After co_await async_add( 8, 13) i = 5 c = 21 [ fib(8) ]
After co_await async_add( 13, 21) i = 6 c = 34 [ fib(9) ]
After co_await async_add( 21, 34) i = 7 c = 55 [ fib(10) ]
About to return_value(55)
About to retrieve value...
Segmentation fault
Почему происходит сбой при получении значения?
Как мне это исправить?
[ godbolt ]
[ wandbox ]
Обновлено
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * .get()
*] * * * * * * * * * * * * * * 1045 Это можно измерить с помощью предварительной проверки.
T await_resume() {
if (val.valid()) {
if constexpr (_DEBUG) std::cout << "About to val.get()..." << std::endl;
t_val = val.get();
if constexpr (_DEBUG) std::cout << "val.get() : " << t_val << std::endl;
}
return t_val; }
К сожалению, похоже на линию
awaitable<int> continua_v = async_fib(std::stoi(str) );
continua_v
почему-то всегда получает значение по умолчанию awaitable<int>
, что нежелательно.
Start
About to val.get()...
val.get() : 2
After co_await async_add( 1, 1) i = 0 c = 2 [ fib(3) ]
About to val.get()...
val.get() : 3
After co_await async_add( 1, 2) i = 1 c = 3 [ fib(4) ]
About to val.get()...
val.get() : 5
After co_await async_add( 2, 3) i = 2 c = 5 [ fib(5) ]
About to val.get()...
val.get() : 8
After co_await async_add( 3, 5) i = 3 c = 8 [ fib(6) ]
About to val.get()...
val.get() : 13
After co_await async_add( 5, 8) i = 4 c = 13 [ fib(7) ]
About to val.get()...
val.get() : 21
After co_await async_add( 8, 13) i = 5 c = 21 [ fib(8) ]
About to val.get()...
val.get() : 34
After co_await async_add( 13, 21) i = 6 c = 34 [ fib(9) ]
About to val.get()...
val.get() : 55
After co_await async_add( 21, 34) i = 7 c = 55 [ fib(10) ]
About to return_value(55)
About to retrieve value...
Retrieving has succeeded : -1
255
[ godbolt ]
[ wandbox ]