• 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();
    }

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

  • 相关阅读:
    Spring MVC3 + Ehcache 缓存实现
    DB2导入导出数据库数据
    JS、ActiveXObject、Scripting.FileSystemObject
    new ActiveXObject("Scripting.FileSystemObject") 时抛出异常 .
    各种浏览器的内核是什么
    Content-Type: application/vnd.ms-excel">
    常用jar包用途
    nutz的json视图
    Nutz中那些好用的工具类
    The JSP specification requires that an attribute name is preceded by whitespace
  • 原文地址:https://www.cnblogs.com/pointer-smq/p/12857426.html
Copyright © 2020-2023  润新知