C++20协程解糖 - 细节简化版

我已经花了10分钟完全了解了C++20协程!

如果你看到这行文字,说明这篇文章被无耻的盗用了(或者你正在选中文字),请前往 cnblogs.com/pointer-smq 支持原作者,谢谢

这篇文章仅展示简化版的控制流解糖,不展示coroutine_handle和各种awaitable的内部实现

被简化掉的部分包括异常处理,传参,await_transform,operator await和new的额外参数

//原

future<int> func1() {
    int result = 0;
    for (int i = 0; i < 10; i++) {
	     result += co_await func2();
	}
	co_return result;
}

int main() {
    auto f = func1();
	//故意不await,仅展示调用
}

解糖之后

//解糖

struct __func1_state : future<int>::promise_type 
{
	int __resume_state = 0;
	int __local_result;
	int __local_i;
	
	any __curr_await; // any只是一个概念上的,就表示这里可能装任何awaitable
	
	void __move_next() {
	__LABEL_START:
		switch (__resume_state) {
		case 0: {//initial suspension point
			__curr_await = this->initial_suspend(); //from promise_type
			__resume_state = 1;
			break; //开始await initial_suspend
		}
		case 1: { //initial suspend后, for的初始化部分
			__curr_await.await_resume(); //initial resume
			__local_result = 0;
			__local_i = 0;
			[[fallthrough]];
		}
		case 2: { //for的co_await前半部分
			if (__local_i < 10) {
				__curr_await = __func2_thunk(); //co_await func2的地方
				__resume_state = 3;
				break; //开始await func2返回的future
			} else { //for结束
				__resume_state = 4;
				goto __LABEL_START;
			}
		}
		case 3: { //for的co_await后半部分
			__local_result += __curr_await.await_resume(); //result += co_await的地方
			__local_i++;
			__resume_state = 2;
			goto __LABEL_START;
		}
		case 4: { //co_return
			this->return_value(__local_result); //from promise_type
			__curr_await = this->final_suspend();
			__resume_state = 5;
			break; //开始await final_suspend
		}
		case 5: { //final suspend返回
			__curr_await.await_resume();
			this->destroy(); //from coroutine_handle
			return; //协程结束,销毁自己,delete this
		}
		} //end switch
		
		// 开始 await __curr_await,上面算出来的
		if (__curr_await.await_ready()) {
			goto __LABEL_START;
		} else {
			auto r = __curr_await.await_suspend(coroutine_handle<int>{this});//coroutine_handle就是一个裸指针的简单包装
			if constexpr (r instance of bool) {
				if (!r) {
					goto __LABEL_START;
				}
			} else if constexpr (r instance of coroutine_handle) {
				r.resume();
			}
			return; //真的暂停协程
		}
	}
};

future<int> __func1_thunk() {
	__func1_state* state = new __func1_state();
	
	future<int> ret = state->get_return_object(); //from promise_type
	
	state.__move_next();

	return ret;
}

int main() {
    auto f = __func1_thunk();
}

看,是不是很简单呢,赶紧自己做一个吧!

posted on 2020-05-09 14:50  PointerSMQ  阅读(1099)  评论(0编辑  收藏  举报