Hero Image
coro_redis 开发手记

本文是coro_redis项目的开发手记,其较为详尽的描述了其开发过程中遇到的问题和解决方案以及学习心得。希望能和大家共同努力和完善此项目。项目地址为: https://github.com/gqw/coro_redis 自从上次写完《从HelloWold开始,深入浅出C++ 20 Coroutine TS》已经有一阵子没有写C++代码了,在那篇文章中给自己立了FLAG说要继续写一篇关于asio中使用协程开发的文章也一直没有兑现。现在趁着空闲用协程写了一个redis client库。 代码还是像mrpc一样追求少而精,希望大家能够学会怎样使用c++的协程,而不是直接把库拿过去用。 协程是从C++20开始被加进标准库的,但是仅支持基本的协程功能,用起来还不是很方便,估计需要等到C++23才能完善(请参考:C++23的目标)。VisualStudio 2022 PREVIEW(ToolSet v143)已经正式支持协程,相关头文件也已经从experimental目录移到正式目录,并且不需再添加 /await 编译选项(v143之前使用协程请参考/await选项说明)。GCC从10.0版本开始支持协程,11.0版本不再是experimental,但还是需要 -fcoroutines 编译选项(请参考:C++ Standards Support in GCC)。 以下是开发使用的环境: windows linux Windows 10 版本 2004 Ubuntu 20.04.2 LTS(wsl2) Visual Studio 2022(v143) GCC 11.1.0 cmake version 3.21.1 cmake version 3.21.1 Vcpkg version 2021-07-26-9425cf5f512f242c0bcbabac31f08832825aee81 Same as Windows 编译说明 安装vcpkg 设置并导出环境变量 VCPKG_ROOT 为 vcpkg 根目录 如果再Winodws下开发,由于Visual Studio还是预览版,vcpkg默认不会使用,所有需要在%VCPKG_ROOT%/triplets目录下添加x86-windows-v143.cmake文件,内容如下: set(VCPKG_TARGET_ARCHITECTURE x86) set(VCPKG_CRT_LINKAGE dynamic) set(VCPKG_LIBRARY_LINKAGE dynamic) set(VCPKG_PLATFORM_TOOLSET "v143") set(VCPKG_DEP_INFO_OVERRIDE_VARS "v143") 安装cmake 执行cmake_build_x64_linux.sh(Linux) 或 cmake_build_x86-v143.bat(Windows)脚本,安装依赖包和生成工程文件 使用方法 协程调用通用命令:

Hero Image
从HelloWold开始,深入浅出C++ 20 Coroutine TS

缘起 前一阵子在查看asio库的时候看到在example目录中已经提供了coroutines_ts代码。很是好奇,便慢慢翻看代码,在感叹Coroutine给异步编程带来的优雅简洁的同时也带来了许多概念上的复杂和难以理解。由于C++ Coroutine还是一个比较新的概念,各个编译器厂商的实现还处于实验性的阶段[1] ,网上的资料少而松散。由此内心涌出一个念头想把自己的学习过程记录下来以期帮助后面学习的人。 从HelloWorld说起 再过两年这个世界的第一条HelloWorld代码就要有50年历史了[2] ,在此先提前蹭下热点,:)… #include <iostream> int main() { std::cout << "hello, world" << std::endl; return 0; } 代码1 这是一段平淡无奇的符合C++98标准的代码,你甚至可以用古董级编译器GCC 4.3都能编译通过[3]。但是我希望通过对这段代码的演化带领大家学习了解C++ 20中的Coroutine。 这段代码的作用很简单,打印一条"hello, world",执行的也很快。但是这个世界并不总是那么简单美好,如果打印的逻辑非常耗时(特别是读取磁盘文件和进行网络请求时)而又需要频繁的调用就有些尴尬了,好了,我们改下代码来模拟这种情形: #include <iostream> #include <thread> #include <chrono> using namespace std::chrono_literals; void remote_query() { // 假设这是个远程网络请求 std::this_thread::sleep_for(4s); std::cout << "hello, world" << std::endl; } int main() { for (;;) { remote_query(); } return 0; } 代码2 改过后的代码不停的进行耗时的远程调用,每次远程调用需要消耗4秒的时间才能返回。可以看到,每次进行调用时程序都要暂停住(也就是卡住)而做不了其它事情。如果这是个带UI(用户界面)的程序,每次进行调用界面就要卡住,用户肯定是不能忍受的。 注意 上面的代码由于使用了thread[4](C++ 11)和chrono_literals[5](C++ 14),所以编译器需要支持C++ 14标准。 多线程+Callback解决方案 为了解决上面的问题,我们对上面的代码进行如下改造: