go-style C++ 协程库 CO 快速上手指南

github

github.com/idealvin/co

参看文档

  • 中文: github gitee
  • English: github gitee

C变量类型有哪些O 是什么

CO 是一个优雅、高效的 C++开源阅览app下载安装 根底库,支撑 Linux, Windows 与 Mac 等途径,它完结了相似 golang 的协程、根据协程的网络编程结构、指令行参数与装备文件解析库、高功用日志库、单元查验结构、JSON 库等一系列高质量的根底组件。

CO 在 g线程池面试题ithub 上以 MIT 许可证开源,它运用了部开源阅览app下载安装分三方代码,或许有不同的许可证,概况见 LICENSE 文件。为了便当国内用户,gitee 上也会守时同步 github 上的代码。

CO 的开展历程

Alvin(idealvin) 自 2013 年开始开发 CO,开始的目的是为了减json字符串少 C++ 项目中的三方依赖,一起前进 C++ 的开发功率。从 2015 年开始,Alvin 将 CO 引入实践项目中,供自己与伙伴运用,大大缩减了项目的开发周期,CO 也得以饱尝工业项目的查验。

通过多年的堆集、沉积,到 2019 年,Alvin 又用 C++ 完结了 golang 中线程和进程的差异是什么的协程机制,并供给了一套根据协程的网络编程结构。CO 协程诞生之初,就被用于嵌入式网络程序开发,并取得了旗开google取胜的作用。

到 2googleplay下载021 年,CO 协程又有了长足的开展,目前在 Linux/google谷歌查找主页Windows/Mac 途径均已支撑 hook,而且完结了协程锁、协程同步作业、协程变量英文池以及 golang 中的 chagoogle翻译nnel 与 waitgroup,用户能够用 CO 写出 golang 的体验。

快速上手

编译

主张设备 xmake,在 CO 根目录实施如下指令构建悉数子项目:

xmake -a

如果需求运用 http::Client, SSL 或 HTTPS 特性,则能够用下面的指令构建:

xmake f --with_libcurl=true --with_openssl=true
xmake -a

xmake 会自动从网络设备 libcurl 与 openssl,视网络情况,这个进程或许会较慢。xmake -a 会构建 libco, gen, co/unitest 以及 co/test 下面的悉数查验代码。用户可开源以实施下面的指json令,作业 CO 中的查验程序:

xmake r unitest -a
xmagoogle谷歌查找主页ke r flag
xmake r log -cout
xmake r co

运用 CO 开发 C++ 项目

最简略的,能够直接包含 co/开源节流all.h,运用 CO 中的悉数特性。如果忧虑影响编译速度,也能够只包含需json文件是干什么的求用到的头文件,如包含 co/co.h,能够运用 co/flag, co/log 以及协程相关的悉数特性。

#include "co/all.h"
DEF_string(s, "nice", "");
int开源阅览app下载安装 main(ijson格局怎样翻开nt argc, char** argv) {
flag::json格局怎样翻开init(argc, argv);
log::init();
LOG << FLG_s;
return 0;
}

上面是一个简略的比如,main 函数前两行分别用于初始化 flag 与 log 库。CO 中的部分组件会用 flag变量提高 界说变量类型有哪些装备项,用 log 打印日志,因而,一般需求在 main 函数开始调用 flag::init()log::init() 进行初始化。JSON

用户也能够用宏 DEF_main 界说开源众包 main 函数:

#ijson格局nclude "co/all.h"
DEF_string(s, "nice", "");
DEF_main(argc, argv) {
LOG << FLG_s;开源阅览app下载安装
return 0;
}

DEF_main 在内部现已调用了 flag::init()log::init(),用户无需再次调用。其他,DEF_main 会将 main 函数中的代码放到协程中作业google翻译,与 golang 保持一致,golang 中的 main 函数也在协程中。CO 中部分协程相关的组件必须在协程中运用,用 CO 开发根据协程的应用程序时,一般主张用 DEF_main 界说 main 函数。

核心组件

co/flag

co/flag 是一个简略易用的指令行参数与装备文件解jsonp析库,CO 中的一些组件会用它界说装备项。

co/flag 为每个装备项供给一个默许值,在没有装备参数的情况下,程序能够按默许装备作业。用户也能够从指令行或装备文变量之间的联系传入装备参数,在需求装备文件时,能够实施 ./exe -mkconf 自动生成装备文件

// xx.cc
#include "co/flag.h"
#include "co/json格局怎样翻开log.h"
DEF_bool(x, false, "变量英文bool x");
DEF_bool(ygoogle地球, false, "bool y");
DEF_uint32(u32, 0, "...")线程的几种状态;
D线程和进程的差异是什么EF_string(s, "hello world", "str开源ing");
int main(int argc,线程撕裂者 char** argv) {
flag变量名的命名规矩::init(argc, argv);
COUT << "x: " << FLG_x;
COUT << "y: " << FLG_变量是什么意思y;
COU线程池面试题T << "u32: " <<jsonp FLG_u32;
COUT << FLG_s &ltjson文件是干什么的;< "|" << FLG_s.size();
return 0;
}

上面是一个运用 co/flag 的比如,代码中 DEF_ 开始的宏,界说了 4 个装备项,每个装备项相当于一个全局变量,变量名是 FLG_ 加装备名。上面的代码编译完后,能够按下面的办法作业:

./xx                  # 按默许装备作业
./xx -xy -s good      # 单字母命名的 bool flag, 能够一起设置为 true
./xx -s "I'm ok"      # 含空格的字符串
./xx开源代码网站github -u32google空间 8k          # 整数能够带单位: k,m,g,t,p, 不区json别大小写
./xx -mkconf          # 自动生成装备文件 xx.conf
./xx xx.conf          # 从装备文件传入参数google翻译
./xx -config xx.con线程池的七个参数f  # 与上同

co/log

co/log 是一个高功用的本地日志系统,CO 中的一些组件会用它打印日志。

co/log 将日志分为 debug, info, warning, error, fatal 5 个等级,打印 fatal 等级的日志会间断程序的作业。用户能够像下面这样打印不同等级的日线程池面试题志:

DLOG << "hello " <变量之间的联系< 23;  // debug
LOG << "hello " << 23;   // info
WLOG << "hello " << 23;  // warning
ELOG <&ljson数据t; "google谷歌查找主页hello " << 23;  /json文件是干什么的/ error
FLOG <<线程安全 "hello " << 23;  // fataljson是什么意思

co/log 还json格局怎样翻开供给了一系列 CHECK 宏,能够视为加强版的 assert,它们在 debug 方法下也不会被清除。

void* p = malloc(32);
CHECK(p != NULL) << "malloc failed..";
CHECK_NE(p, NULL) << "开源节流什么意思malloc failed..";

CHECK 断语失利时,co/log 会打印函线程池创立的四种数调用栈开源阅览app下载安装信息,然后间断程序的作业。

co/log 速度非常快,在程变量提高序作业安稳后,几乎不需求内存分配操作。下面是一些查验效开源阅览果,仅供参看:

  • co/log vs glog (single threa开源d)

    platform google glog co/log
    win2012 HHD 1.6MB/s 180MB/s
    win10 SSD 3google商铺.7MB/s 56变量之间的联系0MB/s
    mac SSD 17MB/s 450MB/s开源矿工
    linux SSD 54MB/s 1023MB/线程s
  • co/l线程和进程的差异是什么og vs spdlog (Windows)

    threads total logs co/log time(seconds) spdljsonog time(seconds)
    1 1000000 0.103619 0.482525
    2 1000000 0.202246 0.565变量英文262
    4 1000000 0.3google地球30694 0.722709
    8 1000000 0.386760 1.322471
  • co/log vs spdlog (Linux)

    threads total logs co/log time(seconds) spdlog time(seconds)
    1 1000000 0.096445 2.006087
    2 1000000 0.142160 3.276006
    4 1000000 0.181407 4.json解析339714
    8 1000000 0.303968 4.700860

c线程池原理o/unitest

co/unitest 是一个简略易用的单元查验结构,CO 中的许多组件会用它写单元查验代码,为 CO 的线程是什么意思安稳性供给了保证。

#include "co/uni开源test.h"
#include "co/os.h"
namespace test {
DEF_test(os) {
DEF_case(homedir) {
EXPECT_NE(os::homedir(), "");
}
DEF_case(cpunum) {
EXPECT_GT(os::cpunum(), 0);
}
}
} // namespace test

上面是一个简略的比如,DEF_test 宏界说了一个查验单元,实践上便是一json解析个函数(类中的办法)。DEF_case 宏界说了查验用例,每个查验用例实践上便是一个代码块google。多个查验单元能够放到同一个 C++ 项目中,main 函数一般json格局怎样翻开只需求下面几行:

#include "co/unitest.h"
int main(int argc, char** argv) {
flag::i开源节流nit(argc, argv);
unit开源中国est::run_all_tests();
return 0;
}

co/unitest 目录下面是 CO 中的单元查验代码,编译后可实施下述指令作业:

xmake r unitest -a   # 作业悉数单元查验变量min表示什么类型的变量用例
xmake r unitest -os  # 仅工变量英文作 os 单元中的查验用例

协程

CO 完结了相似 golang 的协程,它有如下特性:

  • 线程调度,默许线程数为系统 CPU 核数。
  • 同享栈,同一线程中的协程共用若干个栈(大小默许为 1MB),内存占用低,Linux 上的查验显现 1000 万协程只用了 2.8G 内存(仅线程撕裂者供参看)。
  • 各协程之间线程撕裂者为平级联系,能够在任何地变量提高方(包含在协程中)创立新的协程。
  • 支撑系统 API hook (Windows/Linux/Mac),能够直接变量泵在协程中运用三方网络库。
  • 协程化的 socket API。
  • 协程开源中国同步作业 co::Event。
  • 协程锁 co::json解析Mutex。
  • 协程池 co::Pool。
  • channel co::Chan。
  • waitgroup开源是什么意思 co::WaitGroup。

创立协程

go(ku);            // void ku();
go(f, 7);          // void f(int);
go(&线程池创立的四种amp;T::f, &o);     // void T::f(); T o;
go(&T::f, &a线程池原理mp;o, 7);  // void T::f(int); T o;
ggoogle浏览器o([](){
LOG << "hello go";
}线程安全);

上面是用 go() 创立协程的比如,go() 是一个函数,它承受 1 到 3 个参数,第一个参数 f 是恣意可调用的政策,这些参数只需满开源阅览app下载安装f(), (*f)(), f(p), (*f)(p), (o->*f变量与函数)() 或许线程池的七个参数 (o->*f)(p) 能被调用就能够了。

go() 创立的协程会均匀的分配到不同的调度线程中。如果用户想让某些协程作业在同一个线程下,能够用下面的办法创立协程:

auto s =开源节流 co::next_scheduler();
s->go(f1);
s->go(f2);

如果用户想在悉数的调度线程中创立协程,能够用下面的办法:

auto& s = co::all_schedulers();
for (size_t i = 0; i < s.size(); ++i) {
s[i]->go(f);
}

channel

co::Chan,相似于 golang 中的 channel,可用于在协程之间传递数线程池面试题据。

#includejson解析 "co/co.h"
DEF_main(arjson格局怎样翻开gc, argv) {
co::Chan&l开源节流t;int> ch;
go([ch]() {
ch << 7;
});
int v = 0;
ch >> v;
LOG <&变量英文lt; "v: " << v;
re变量是什么意思turn 0;
}

channel 的读写操作必须在协程中进行,因而上述代码顶用 DEF_main 界说 main 函数,让 main 函数中的代码也作业在协程中。

代码中的 channel 政策在栈上,而 CO 选用的是同享栈完结办法,一个协程栈上的数据或许被其他协程掩盖,协程间一般不能直接通过栈上的数据通信,因而代码中的 lambda 选用了按值捕获的办法,将 channel 拷贝了json数据一份,传递到新建的协开源节流程中。channel 的拷贝操作仅仅将内部引证计数加 1,几乎不会对功用形成影响。

创立 channel 时能够像下面这样加上超时时间:

co::Chan<int> ch(8, 1000);

channel 读写操作结束后,能够调用 co::timeout()变量类型有哪些 判别是否超时,这种办法比 golang 中根据 select 的完结办法更简略。

CO 中的 changoogleplaynel 根据内存拷贝完结,传递的数据类型能够是内置类型、指针类型,或许拷贝操作具有简略的内存拷贝语义的结构体类型。像 std::str开源阅览ing开源矿工 STL 中的容器类型,拷贝操作线程和进程的差异是什么不是简略的内存拷贝,一般不能直接在 channejson字符串l 中传递,概况见 co::Chan 参看文档。

waitgroup

co::WaitGroup,相似于 golang 中的变量与函数 sync.WaitGroup,可用于等候协程或线程的退出。

#include "co/co.h"
DEF_main(argc, argv) {
FLG_cout = tr开源众包ue;
co::WaitGroup wg;
wg.adjsonpd(8);
for (int i = 0; i < 8; ++i) {
go([wgjson接口返回过错]() {
LOG << "co: " << co::coroutine_id();
wg.done();
});
}
wg.wait();
return 0;
}

网络编json接口返回过错json文件是干什么的

CO 供给了一套协程google化的 socke变量与函数t API,它们大部分方法上与原生的 socket API 根柢一致,了解 socket 编程的用户,能够轻松的用同步的办法写出高功用的网络程序。其他,CO 也完结了更高层的网络编程组件,包含 TCP、HTTP 以及根据 JSON变量名的命名规矩 的 RPC 结构,它们兼容 IPv6线程池,一起支撑 SSL,用起来比 socket API 更便当。这里只简略的展示一下 HTTP 的用法,其他的能够检查参看文档。

静态 w开源众包eb server

#include "co/flag.h"
#include "co/log.h"
#include "co线程池创立的四种/so.h"
DEF_string(d, ".", "root dir"); // Specify the root directory of th线程和进程的差异是什么e web server
int main(int argc, char** argv) {
flag::init(开源阅览app下载安装argc, argv);
log::线程init();
so::egoogle谷歌查找主页asy(FLG_d.c_str()); // mum never have tgoogle地球o worry again
return 0;
}

HTTP server

http::Server serv;
serv.on_req(
[](const http::Req& req, http::Res&am开源p; res) {
if (req.is_method_get()) {
if (req.url() == "/hello") {
res.set_status(200);
res.setjson字符串_body("hello world");
} else {
res.set_status(404);
}
} else {
res.set_status(405); // method not allowed
}
}
);
serv.start("0.0.0.0", 80);                                    // http
s线程池创立的四种erv.start("变量名的命名规矩0.0.0.0", 443, "privkey.pem", "certificate.pem"); // https

HTTP client

void f() {
http::Client c("https://github.com");
c.变量是什么意思gegoogle服务结构t("/Google");
LOG << "response code: "<< c.respons线程e_code();
LOG <&ltgoogle商铺; "body size: "<< c.b变量与函数ody_size();
LOG <&变量提高lt; "Content-Length: "<< c.header("Content-Length");
LOG <变量的界说< c.heade线程池的七个参数r();
c.post("/hello", "data xxx");
LOG << "response code: "<< c.r开源是什么意思esponse_code();
}
go(f);

发表评论

提供最优质的资源集合

立即查看 了解详情