Giter Club home page Giter Club logo

gitalk's People

Watchers

 avatar

gitalk's Issues

String utilities | Book for CO

https://idealvin.github.io/en/co/str/

include: co/str.h.
#split, strip, replace #str::split std::vector split(const char* s, char c, uint32 n=0); std::vector split(const fastring& s, char c, uint32 n=0); std::vector split(const char* s, const char* c, uint32 n=0); std::vector split(const fastring& s, const char* c, uint32 n=0); This function splits the string into several substrings, the original string remains unchanged, and returns the split result.
Parameter s is a C string or fastring, parameter c is the separator, parameter n is the maximum number of splits, 0 or -1 means unlimited.

字符流(fastream) | Book for CO

https://idealvin.github.io/cn/co/fastream/

include: co/fastream.h.
#fastream fastream 用于取代 C++ 标准库中的 std::ostringstream。std::ostringstream 性能较差,实测比 snprintf 慢好几倍,fastream 在不同平台测试比 snprintf 快 10~30 倍左右。
#fastream::fastream fastream() noexcept; explicit fastream(size_t cap); fastream(fastream&& s) noexcept; 第 1 个是默认构造函数,创建一个空的 fastream 对象,内部不会分配任何内存。
第 2 个构造函数用参数 cap 指定 fastream 的初始容量,即预分配 cap 字节的内存。
第 3 个是 move 构造函数,不会进行内存拷贝。
示例
fastream s; // 状态为空的 fastream, 未分配内存 fastream s(1024); // 预分配 1k 内存 fastream x(std::move(s); // move 构造函数, s 变成空对象 #fastream::operator= fastream& operator=(fastream&& s) noexcept; fastream 只支持 move 赋值操作,s 的内容被转移到 fastream 中,s 自身变成空对象。

TCP | Book for CO

https://idealvin.github.io/cn/co/net/tcp/

include: co/so/tcp.h.
#tcp::Connection tcp::Connection 类是对 TCP 连接的简单封装,用于实现服务端代码,客户端不需要用这个类。当服务端启用 SSL 时,tcp::Connection 会用 SSL 传输数据。
#Connection::Connection Connection(sock_t s); 构造函数,参数 s 是 socket 描述符。 #Connection::~Connection Connection::~Connection(); 析构函数,调用 close() 关闭连接。 #Connection::close virtual int close(int ms = 0); 关闭连接,参数 ms > 0 时,延迟一段时间再关闭连接。 此方法必须在 I/O 线程(一般是进行 I/O 操作的协程)中调用。 #Connection::recv virtual int recv(void* buf, int n, int ms=-1); 接收数据,与 co::recv 类似。 此方法必须在协程中调用。 此方法成功时返回值 >0,超时或发生错误时返回值 <0,对端关闭连接时返回 0。 #Connection::recvn virtual int recvn(void* buf, int n, int ms=-1); 接收指定长度的数据,与 co::recvn 类似。 此方法成功时返回 n,超时或发生错误时返回值 <0,对端关闭连接时返回 0。 #Connection::reset virtual int reset(int ms = 0) 重置 TCP 连接,与 close() 不同,它不会进入 TIME_WAIT 状态。参数 ms > 0 时,延迟一段时间再重置连接。 此方法必须在 I/O 线程(一般是进行 I/O 操作的协程)中调用。 #Connection::send virtual int send(const void* buf, int n, int ms=-1); 发送数据,与 co::send() 类似。 此方法成功时返回 n,超时或发生错误时返回值 <=0。 #Connection::socket sock_t socket() const; 返回内部的 socket 描述符,连接已关闭时返回 -1。 #Connection::strerror virtual const char* strerror() const; Connection 中的方法出错时,可以调用此方法查看错误信息。 #tcp::Server tcp::Server 是基于协程的 TCP 服务端,它的特性如下:

Sponsor💕 | Book for CO

https://idealvin.github.io/en/about/sponsor/

#Sponsor CO is a personal project. If you are interested in sponsoring CO, you can contact with Alvin ([email protected]), we’ll display your logo, website and other information here, and also provide you with better technical services. Thank you very much🙏
#Coffee If you like CO, you may also consider giving the author a cup of coffee, thanks🙏
Wechat
Alipay

字节序 | Documents for Coost

https://coostdocs.github.io/cn/co/net/byte_order/

include: co/byte_order.h.
计算机中的数据在内存中是以字节(8 bit)为基本单位进行存储的,大端机采用大端字节序,即高位字节在低地址,低位字节在高地址,小端机则采用小端字节序,即低位字节在低地址,高位字节在高地址。
单个字节在大、小端机器上是完全相同的,而多个字节的基本数据类型,在大、小端机器上有着不同的字节序。这里说的基本数据类型是指像 int, double 这样的内置类型,字符串不在此列,它是由单字节构成的序列,在大、小端机器上有着相同的存储形式。
网络上传输的数据采用大端字节序,所谓的网络字节序也就是大端字节序。发送数据到网络上时,需要将其中的多字节基本类型转换成网络字节序,而从网络上接收数据时,则需要转换成所在主机的字节序。
byte_order.h 定义了如下的方法:
ntoh16 ntoh32 ntoh64 hton16 hton32 hton64 这些方法分别适用于长度为 2, 4, 8 字节的整数,其中 ntoh 系列将网络字节序转换成主机字节序,hton 系列则将主机字节序转换成网络字节序。
代码示例 uint32 h = 777; uint32 n = hton32(h);

定时任务 | Book for CO

https://idealvin.github.io/cn/co/tasked/

include: co/tasked.h.
#Tasked Tasked 类是一个简单的定时任务调度器,内部由单线程调度所有任务,但可以从任意线程添加任务。Tasked 中的任务阻塞时,会影响后面的所有任务,因此不推荐用 Tasked 调度可能会长时间阻塞的任务。
#Tasked::Tasked Tasked(); Tasked(Tasked&& t); 第 1 个版本是默认构造函数,对象创建完,调度线程即开始运行。 第 2 个版本是 move 构造函数,支持将 Tasked 对象放到 STL 容器中。 #Tasked::~Tasked ~Tasked(); 析构函数,退出任务调度线程。 #Tasked::F typedef std::function<void()> F; 任务类型,固定为 std::function<void()> 类型的函数。 #Tasked::run_at void run_at(F&& f, int hour, int minute=0, int second=0); void run_at(const F& f, int hour, int minute=0, int second=0); 添加指定时刻运行的任务,f 将在 hour:minute:second 时刻运行一次。 hour 必须是 0-23 之间的整数,minute 与 second 必须是 0-59 之间的整数,默认为 0。 #Tasked::run_daily void run_daily(F&& f, int hour=0, int minute=0, int second=0); void run_daily(const F& f, int hour=0, int minute=0, int second=0); 添加每天指定时刻运行的周期性任务,f 将在每天的 hour:minute:second 时刻运行一次。 hour 必须是 0-23 之间的整数,默认为 0,minute 与 second 是 0-59 之间的整数,默认为 0。 #Tasked::run_every void run_every(F&& f, int n); void run_every(const F& f, int n); 添加每 n 秒运行一次的周期性任务。 #Tasked::run_in void run_in(F&& f, int n); void run_in(const F& f, int n); 添加 n 秒后运行一次的任务。 #Tasked::stop void stop(); 退出任务调度线程,析构函数中会自动调用此方法。 多次调用此方法是安全的。 #代码示例 Tasked s; // create and start the scheduler s.

Introduction | Book for CO

https://idealvin.github.io/en/about/co/

#What is CO CO is an elegant and efficient C++ base library that supports Linux, Windows and Mac platforms. It implements a series of high-quality base components, such as go-style coroutine, coroutine-based network programming framework, command line parameter and config file parsing library, high-performance log library, unit testing framework, JSON library, etc.
CO is an open source project on github under the MIT license. It contains code from some other projects, which may have different licenses, see LICENSE file for details.

线程 | Book for CO

https://idealvin.github.io/cn/co/thread/

include: co/thread.h.
#线程(Thread) Thread 类是对线程的封装,创建 Thread 对象时,线程就会启动,线程一旦启动,就会一直运行,直到线程函数退出。Thread 类并不提供强制退出线程的方法(类似于 pthread_cancel),这类方法通常不安全,可能对用户数据造成破坏。
#Thread::Thread explicit Thread(co::Closure* cb); template explicit Thread(F&& f); template<typename F, typename P> Thread(F&& f, P&& p); template<typename F, typename T, typename P> Thread(F&& f, T* t, P&& p); 构造函数,Thread 对象创建完,线程就会启动。
第 1 个版本,参数 cb 是 Closure 类型的指针,一般不建议用户直接用这个版本。
第 2-4 个版本,根据传入的参数构造一个 Closure 对象,然后调用第 1 个版本进行初始化。
第 2 个版本,参数 f 是任意可调用的对象,只要能调用 f() 或 (*f)() 就行。

HTTP | Book for CO

https://idealvin.github.io/cn/co/net/http/

include: co/so/http.h.
#http::Client http::Client 是基于协程的 http 客户端,它基于 libcurl 实现。
#Client::Client explicit Client(const char* serv_url); 构造函数,参数 serv_url 是服务器的 url 地址,它的形式是 protocol://host:port,下面的 server url 都是合理的: “github.com” “https://github.com”http://127.0.0.1:7788” “http://[::1]:8888” http::Client 对象创建时,并没有建立连接。 #Client::~Client Client::~Client(); 析构函数,关闭连接,释放 libcurl 相关资源。 #Client::add_header void add_header(const char* key, const char* val); void add_header(const char* key, int val); 添加 HTTP 头部,用户在进行 HTTP 请求前,可以用此方法添加头部,这些头部会自动添加到后续所有请求中。 第 2 个版本中,参数 val 是整数,内部自动转换成字符串。 #Client::body const char* body() const; 获取当前 HTTP 请求的响应体,返回一个指针,用户需要用 body_size() 方法获取它的长度。 #Client::body_size size_t body_size() const; 返回当前 HTTP 请求的响应体长度。 #Client::close void close(); 关闭 HTTP 连接,需要在协程中调用此方法。 调用此方法后,http::Client 对象就不能再用了。 #Client::del void del(const char* url, const char* s, size_t n); void del(const char* url, const char* s); void del(const char* url); HTTP **DELETE 请求,必须在协程中调用。 参数 url 必须是 '/' 开头的字符串。 前两个版本,适用于带 body 部分的 DELETE 请求,参数 s 是 body,n 是 s 的长度,第 2 个版本 s 以 ‘\0’ 结尾。 第 3 个版本适用于不带 body 的 DELETE 请求。 #Client::easy_handle void easy_handle() const; 返回 libcurl 的 easy handle。 #Client::get void get(const char url); HTTP **GET *请求,必须在协程中调用。 参数 url 必须是 '/' 开头的字符串。 #Client::head void head(const char url); HTTP *HEAD 请求,必须在协程中调用。 参数 url 必须是 '/' 开头的字符串。 #Client::header const char header(const char key); const char header() const; 第 1 个版本获取当前 HTTP 响应中 header 的值,header 不存在时,返回一个空字符串。

命令行参数与配置文件解析 | Book for CO

https://idealvin.github.io/cn/co/flag/

include: co/flag.h.
#基本概念 co/flag 是一个类似 google gflags 的命令行参数及配置文件解析库,其原理很简单,代码中定义全局变量,然后在程序启动时解析命令行参数或配置文件,修改这些全局变量的值。
#flag 变量 co/flag 中的宏定义的全局变量,称为 flag 变量。如下面的代码定义了一个 flag 变量,变量名是 FLG_x。
DEF_bool(x, false, "xxx"); // bool FLG_x = false; co/flag 支持 7 种类型的 flag 变量:
bool, int32, int64, uint32, uint64, double, string 每个 flag 变量都有一个默认值,用户可以通过命令行参数或配置文件修改 flag 变量的值。如前面定义的 FLG_x,在命令行中可以用 -x=true,在配置文件中可以用 x = true,设置一个新的值。
#command line flag 命令行参数中,以 -x=y 的形式出现,其中 x 被称为一个 command line flag(以下简称为 flag)。命令行中的 flag x 对应代码中的全局变量 FLG_x,命令行中的 -x=y 就相当于将 FLG_x 的值设置为 y。为了方便,下面可能将 flag 与 flag 变量统一称为 flag。

原子操作 | Documents for Coost

https://coostdocs.github.io/cn/co/concurrency/atomic/

include: co/atomic.h.
#Memory Order coost 从 v3.0 开始,增加了对 memory order 的支持。coost 中的 6 种 memory order 定义如下:
enum memory_order_t { mo_relaxed, mo_consume, mo_acquire, mo_release, mo_acq_rel, mo_seq_cst, }; 为了保持兼容性,coost 中的原子操作默认的 memory order 均为 mo_seq_cst。
#v3.0 删除的 API atomic_get,使用 atomic_load 取代之。 atomic_set,使用 atomic_store 取代之。 atomic_reset,使用 atomic_store(&x, 0) 取代之。 #load & store #atomic_load template inline T atomic_load(const T* p, memory_order_t mo = mo_seq_cst); 此函数获取 p 指向的变量的值,T 是长度为 1, 2, 4, 8 字节的任意内置数据类型(包括指针类型)。

基本概念 | Documents for Coost

https://coostdocs.github.io/cn/co/concurrency/coroutine/basic/

#协程基本概念 协程是运行于线程中的轻量级调度单位。 协程之于线程,类似于线程之于进程。 一个进程中可以存在多个线程,一个线程中可以存在多个协程。 协程所在的线程一般被称为调度线程。 协程发生 io 阻塞或调用 sleep 等操作时,调度线程会挂起此协程。 协程挂起时,调度线程会切换到其他等待中的协程运行。 协程的切换是在用户态进行的,比线程间的切换更快。 协程非常适合写网络程序,可以实现同步的编程方式,不需要异步回调,大大减轻了程序员的**负担。
#co 协程特性 coost 中实现的是一种类似 goroutine 的协程,有如下特性:
支持多线程调度,默认线程数为系统 CPU 核数。 共享栈,同一线程中的协程共用若干个栈(大小默认为 1MB),内存占用低,Linux 上的测试显示 1000 万协程只用了 2.8G 内存(仅供参考)。 协程创建后,始终在同一个线程中运行,而不会切换到其他线程。 各协程之间为平级关系,可以在任何地方(包括在协程中)创建新的协程。 coost 协程库中 context 相关代码取自 ruki 的 tbox,而 tbox 则参考了 boost 的实现,在此表示感谢!

Coroutine | Book for CO

https://idealvin.github.io/en/co/coroutine/

include: co/co.h.
#Basic concepts Coroutines are lightweight scheduling units that run in threads. Coroutines are to threads, similar to threads to processes. There can be multiple threads in a process and multiple coroutines in a thread. The thread where the coroutine runs in is generally called the scheduling thread. The scheduling thread will suspend a coroutine, if it blocks on an I/O operation or sleep was called in the coroutine.

协程 | Book for CO

https://idealvin.github.io/cn/co/coroutine/

include: co/co.h.
#基本概念 协程是运行于线程中的轻量级调度单位。 协程之于线程,类似于线程之于进程。 一个进程中可以存在多个线程,一个线程中可以存在多个协程。 协程所在的线程一般被称为调度线程。 协程发生 io 阻塞或调用 sleep 等操作时,调度线程会挂起此协程。 协程挂起时,调度线程会切换到其他等待中的协程运行。 协程的切换是在用户态进行的,比线程间的切换更快。 协程非常适合写网络程序,可以实现同步的编程方式,不需要异步回调,大大减轻了程序员的**负担。
co 协程库实现的是一种类似 golang 的协程,有如下特性:
支持多线程调度,默认线程数为系统 CPU 核数。 共享栈,同一线程中的协程共用若干个栈(大小默认为 1MB),内存占用低,Linux 上的测试显示 1000 万协程只用了 2.8G 内存(仅供参考)。 协程创建后,始终在同一个线程中运行,而不会切换到其他线程。 各协程之间为平级关系,可以在任何地方(包括在协程中)创建新的协程。 co 协程库在 linux, mac, windows 等平台,分别基于 epoll, kqueue, iocp 实现。
co 协程库中 context 切换相关的代码,取自 ruki 的 tbox,而 tbox 则参考了 boost 的实现,在此表示感谢!
#协程 API #go void go(Closure* cb); template void go(F&& f); template<typename F, typename P> void go(F&& f, P&& p); template<typename F, typename T, typename P> void go(F&& f, T* t, P&& p); 此函数用于创建协程,与创建线程类似,需要指定一个协程函数。

defer | Book for CO

https://idealvin.github.io/cn/co/defer/

include: co/defer.h.
#defer defer 是 CO 提供的一个宏,它实现了类似 golang 中 defer 的功能。
#include "co/defer.h"#include "co/time.h"#include "co/log.h"#include "co/json.h" void f(const Json& req, Json& res) { Timer t; LOG << "req: " << req; defer(LOG << "res: " << res << ", time elapse: " << t.us() << "us"); // do something here } 上面的例子中,defer 中的代码将在函数 f 结束时执行,从而打印出函数的输出及调用时间。

IO 事件 | Documents for Coost

https://coostdocs.github.io/cn/co/concurrency/coroutine/io_event/

include: co/co.h.
#co::_ev_t enum _ev_t { ev_read = 1, ev_write = 2, }; I/O 事件类型,ev_read 表示读,ev_write 表示写。 #co::io_event co::io_event 用于将非阻塞 I/O 转换为同步方式。用户在协程中对一个 non-blocking socket 进行 I/O 操作,当 socket 不可读或不可写时,用户调用 co::io_event 的 wait() 方法挂起协程,等待 I/O 事件;当 socket 变为可读或可写时,调度线程唤醒该协程,继续 I/O 操作。
#constructor 1. io_event(sock_t fd, _ev_t ev); 2. io_event(sock_t fd, int n=0); // for windows only 1, 参数 fd 是一个 non-blocking socket,参数 ev 是 ev_read 或 ev_write 中的一种。调用 wait() 方法会在 socket 上等待 ev 指定的 I/O 事件,wait() 成功返回时,需要用户调用 recv, send 等函数完成 I/O 操作。在 windows 平台,fd 必须是 TCP socket(对于 UDP,很难用 IOCP 模拟 epoll 或 kqueue 的行为)。 2, 仅适用于 windows,fd 可以是 UDP socket,但用户需要手动调用 WSARecvFrom, WSASendTo 等函数向 IOCP 发送 overlapped I/O 请求,然后调用 wait() 方法,当 wait() 成功返回时,表示 IOCP 已经帮用户完成了 I/O 操作。具体的用法此处不详述,代码中有详细的注释,建议直接参考 co::io_event 的源码,以及 windows 上 co::accept, co::connect, co::recvfrom, co::sendto 的实现。 #destructor ~io_event(); 析构函数,从 epoll 或 kqueue 中移除之前注册的 I/O 事件。 #wait bool wait(uint32 ms=-1); 此方法等待 socket 上的 I/O 事件,参数 ms 是超时时间,单位为毫秒,默认为 -1,永不超时。 此方法阻塞,直到 I/O 事件到来,或者超时、发生错误。 此方法成功时返回 true,超时或发生错误时返回 false。 #代码示例 int recv(sock_t fd, void* buf, int n, int ms) { const auto sched = xx::gSched; CHECK(sched) << "must be called in coroutine.

日志 | Book for CO

https://idealvin.github.io/cn/co/log/

include: co/log.h.
#基本介绍 co/log 是一个类似 google glog 的 C++ 流式日志库,它像下面这样打印日志:
LOG << "hello world" << 23; co/log 将日志分为 debug, info, warning, error, fatal 5 个级别,并提供一系列的宏,用于打印不同级别的日志。打印 fatal 级别的日志会终止程序的运行,co/log 还会在程序退出前打印函数调用栈信息,以方便追查程序崩溃的原因。
co/log 内部采用异步的实现方式,日志先写入缓存,达到一定量或超过一定时间后,由后台线程一次性写入文件,性能在不同平台比 glog 提升了 20~150 倍左右。下表是不同平台单线程连续打印 100 万条(每条 50 字节左右) info 日志的测试结果:
log vs glog google glog co/log win2012 HHD 1.6MB/s 180MB/s win10 SSD 3.7MB/s 560MB/s mac SSD 17MB/s 450MB/s linux SSD 54MB/s 1023MB/s #初始化及关闭日志系统 #log::init void init(); 此函数初始化 log 库,并启动日志线程,需要在 main 函数开头调用一次。

同步事件 | Documents for Coost

https://coostdocs.github.io/cn/co/concurrency/coroutine/event/

include: co/co.h.
#co::event co::event 是协程间的一种同步机制,它与线程中的 co::sync_event 类似。
从 v2.0.1 版本开始,co::event 可以在协程与非协程中使用。 #constructor 1. explicit event(bool manual_reset=false, bool signaled=false); 2. event(event&& e); 3. event(const event& e); 1, 与线程中的 co::sync_event 类似。 2, 移动构造函数。 3, 拷贝构造函数,仅将内部引用计数加 1。 #reset void reset() const; 将事件重置为未同步状态。 #signal void signal() const; 产生同步信号,将事件设置成同步状态。 所有 waiting 状态的协程或线程会被唤醒。若当前并没有 waiting 状态的协程或线程,则下一个调用 wait() 方法的协程或线程会立即返回。 #wait 1. void wait() const; 2. bool wait(uint32 ms) const; 1, 等待直到事件变成同步状态。 2, 等待直到事件变成同步状态或超时。参数 ms 指定超时时间,单位为毫秒。若事件变成同步状态,返回 true,否则返回 false。 当构造函数中 manual_reset 为 false 时,wait() 结束时会自动将事件设置成未同步状态。 #代码示例 #include "co/co.

RPC | Book for CO

https://idealvin.github.io/cn/co/net/rpc/

include: co/so/rpc.h.
co/rpc 是一个类似 grpc 与 thrift 的 RPC 框架,只不过它使用 JSON 格式传输数据,而不是 protobuf, thrift 等二进制协议。
#rpc::Service rpc::Service 是一个接口类,它表示一个 service,一个 RPC server 中可以包含多个 service。
#Service::name virtual const char* name() const = 0; 返回 service 的名字,该名字包含包名,如 “xx.yy.HelloWorld”。 RPC 请求中,必须带一个 **“service” **字段,它的值就是 service 的名字。 #Service::process virtual void process(const Json& req, Json& res) = 0; 该方法处理 RPC 请求,结果被填充到参数 res 中。 server 接收到 RPC 请求时,根据 req 中的 “service” 字段找到对应的 service,然后调用该 service 的 process() 方法处理该请求。 #rpc::Server rpc::Server 基于 tcp::Server 实现,它支持 SSL 以及用户名与密码认证。几年前的测试结果显示,单线程 QPS 可以达到 120k+。

Basic definitions | Book for CO

https://idealvin.github.io/en/co/def/

include: co/def.h.
#typedefs #Fixed-length integer type def.h defines the following 8 types of integers:
typedef int8_t int8; typedef int16_t int16; typedef int32_t int32; typedef int64_t int64; typedef uint8_t uint8; typedef uint16_t uint16; typedef uint32_t uint32; typedef uint64_t uint64; These types have the same length on different platforms, and there is no portability problem. Google Code Style recommends not to use built-in integer types such as short, long, long long, etc.

面向玄学 | Documents for Coost

https://coostdocs.github.io/cn/co/god/

include: co/god.h.
#god god 模块提供了一些与模板相关的功能,模板用到深处有点玄,一些 C++ 程序员将之称为面向玄学编程。
#god::bless_no_bugs void bless_no_bugs(); 祈求老天保佑代码无 bug,线程安全,可任意调用。
示例
#include "co/god.h" #include "co/cout.h" int main(int argc, char** argv) { god::bless_no_bugs(); co::print("hello world"); return 0; } #god::cast template<typename To, typename From> constexpr To cast(From&& f) { return (To) std::forward(f); } 万能转换,将 From 类型转换为 To 类型,To 可以是引用。
示例
int i = 65; char c = god::cast(i); // c -> 'A' god::cast<char&>(i) = 'a'; // 将 i 的低字节设置为 'a' #————— #god::align_down 1.

更新日志 | Book for CO

https://idealvin.github.io/cn/about/update/

#v2.0.1 #参考文档 中文: github gitee English: github gitee #新特性 xrepo xrepo install -f "openssl=true,libcurl=true" co vcpkg vcpkg install co:x64-windows # http & ssl support vcpkg install co[libcurl,openssl]:x64-windows defer (类似于 golang 中的 defer) #include "co/defer.h"Timer t; defer(LOG << "time elapse: " << t.us() << "us"); channel (类似于 golang 中的 channel) #include "co/co.h" DEF_main(argc, argv) { co::Chan ch; go(ch { ch << 7; }); int v = 0; ch >> v; LOG << "v: "<< v; return 0; } waitgroup (类似于 golang 中的 sync.

线程 | Documents for Coost

https://coostdocs.github.io/cn/co/concurrency/thread/

include: co/co.h.
#线程 v3.0.1 删除了 co/thread.h 头文件,移除了全局的 Thread 与 Mutex 类,其功能与 C++11 中的 std::thread 与 std::mutex 一样,用户可以直接使用 std 版本。 #co::thread_id uint32 thread_id(); 返回当前线程的 id 值。 #co::sync_event 同步事件是多线程间的一种同步机制,适用于生产者-消费者模型。消费者线程调用 wait() 方法等待同步信号,生产者线程则调用 signal() 方法产生同步信号。co::sync_event 支持多生产者、多消费者,但实际应用中,单个消费者的情况比较多。
v3.0.1 移除了全局范围的 SyncEvent,请使用 co::sync_event 替代之。 #constructor explicit sync_event(bool manual_reset=false, bool signaled=false); 构造函数,参数 manual_reset 表示是否手动将同步状态设置成未同步,参数 signaled 表示初始状态是否为同步状态。 #sync_event::reset void reset(); 将事件设置成未同步状态。 当构造函数中 manual_reset 为 true 时,用户在调用 wait() 后需要手动调用此方法,将事件设置成未同步状态。 #sync_event::signal void signal(); 产生同步信号,将事件设置成同步状态。 #sync_event::wait 1. void wait(); 2. bool wait(uint32 ms); 1, 一直等待直到事件变成同步状态。 2, 等待直到事件变成同步状态或超时。参数 ms 指定超时时间,单位为毫秒。若事件变成同步状态,返回 true,否则返回 false。 当构造函数中 manual_reset 为 false 时,wait() 结束时会自动将事件设置成未同步状态。 #代码示例 #include "co/co.

时间 | Book for CO

https://idealvin.github.io/cn/co/time/

include: co/time.h.
#epoch time epoch 是一个特定的时刻 1970-01-01 00:00:00 UTC,epoch time 是从 epoch 时刻开始的时间,它受系统时间影响。
#epoch::ms int64 ms(); 返回自 epoch 到当前时刻的时间,单位为毫秒。 #epoch::us int64 us(); 返回自 epoch 到当前时刻的时间,单位为微秒。 #monotonic time monotonic time 是单调递增时间,大多数平台实现为自系统启动开始的时间,一般用于计时,比系统时间稳定,不受系统时间的影响。
#now::ms int64 ms(); 返回一个单调递增的时间戳,单位为毫秒。 在 mac 平台,如果系统不支持 CLOCK_MONOTONIC,则使用 epoch::ms()。 #now::us int64 us(); 返回一个单调递增的时间戳,单位为微秒。
在 mac 平台,如果系统不支持 CLOCK_MONOTONIC,则使用 epoch::us()。
示例
int64 beg = now::us(); int64 end = now::us(); LOG << "time used: " << (end - beg) << " us"; #时间字符串(now::str) // fm: 时间输出格式 fastring str(const char* fm="%Y-%m-%d %H:%M:%S"); 此函数以指定格式返回当前系统时间的字符串形式,它基于 strftime 实现。

字符串(fastring) | Book for CO

https://idealvin.github.io/cn/co/fastring/

include: co/fastring.h.
#fastring fastring 是 co 中的字符串类型,它实现了 std::string 中的大部分方法,同时也提供了一些 std::string 没有的方法。
#fastring::fastring 1. fastring() noexcept; 2. explicit fastring(size_t cap); 3. fastring(const void* s, size_t n); 4. fastring(const char* s); 5. fastring(const std::string& s); 6. fastring(size_t n, char c); 7. fastring(char c, size_t n); 8. fastring(const fastring& s); 9. fastring(fastring&& s) noexcept; 第 1 个是默认构造函数,创建一个空的 fastring 对象,不会分配任何内存。
第 2 个构造函数同样创建一个空的 fastring 对象,但用参数 cap 指定初始容量,即预分配 cap 字节的内存。
第 3 个构造函数从给定的字节序列创建 fastring 对象,参数 n 是序列长度。

co/flag | Documents for CO

https://idealvin.github.io/en/co/flag/

include: co/flag.h.
#Basic concepts co/flag is a command line and config file parsing library similar to google gflags. Its principle is very simple, define global variables in code, then parse the command line parameters or config file when the program starts, and update the value of these global variables.
#flag variable The global variable defined by macros in co/flag are called flag variable. For example, the following code defines a flag variable, the variable name is FLG_x.

APIs | Documents for Coost

https://coostdocs.github.io/cn/co/concurrency/coroutine/api/

include: co/co.h.
#Coroutine APIs v3.0 移除了 co::init, co::exit, co::stop。 #go 1. void go(Closure* cb); 2. template void go(F&& f); 3. template<typename F, typename P> void go(F&& f, P&& p); 4. template<typename F, typename T, typename P> void go(F&& f, T* t, P&& p); 此函数用于创建协程,与创建线程类似,需要指定一个协程函数。
1, 参数 cb 指向一个 Closure 对象,协程启动后会调用 Closure 中的 run() 方法。
2-4, 将传入的参数打包成一个 Closure,然后调用 1。
2, 参数 f 是任意可调用的对象,只要能调用 f() 或 (*f)() 就行。
3, 参数 f 是任意可调用的对象,只要能调用 f(p), (*f)(p) 或 (p->*f)() 就行。

基准测试 | Documents for Coost

https://coostdocs.github.io/cn/co/benchmark/

include: co/benchmark.h.
#基本概念 co.benchmark 是 v3.0.1 新增的基准测试框架,可用于性能基准测试。
#BM_group #define BM_group(name) \ ...... \ void co_bm_group##name(bm::xx::Group& g) BM_group 宏用于定义基准测试组,实际上定义了一个函数。 每个 group 内可以用 BM_add 定义多条基准测试。 参数 name 是组名,也是所定义函数名的一部分,如 BM_group(atomic) 是合理的,而 BM_group(co.atomic) 则是不允许的。 #BM_add #define BM_add(name) \ g.bm = #name; \ _BM_add BM_add 宏用于定义基准测试,它必须在 BM_group 定义的函数内使用。 参数 name 是基准测试名,与 BM_group 不同,BM_add(co.atomic) 也是允许的。 #BM_use #define BM_use(v) bm::xx::use(&v, sizeof(v)) BM_use 宏告诉编译器变量 v 会被使用,防止编译器将一些测试代码优化掉。 #编写基准测试代码 #测试代码示例 #include "co/benchmark.h" #include "co/mem.h" BM_group(malloc) { void* p; BM_add(::malloc)( p = ::malloc(32); ); BM_use(p); BM_add(co::alloc)( p = co::alloc(32); ); BM_use(p); } int main(int argc, char** argv) { flag::parse(argc, argv); bm::run_benchmarks(); return 0; } 上面的代码定义了一个名为 malloc 的基准测试组,组内用 BM_add 添加了 2 个基准测试。 调用 bm::run_benchmarks(),会执行所有的基准测试代码。 上例中,若无 BM_use(p),编译器可能认为 p 是未使用的变量,将相关的测试代码优化掉,导致无法测出准确的结果。 #测试结果示例 基准测试结果输出为 markdown 表格,可以轻松将测试结果复制到 markdown 文档中。 多个 BM_group 会生成多个 markdown 表格。 表格第 1 列是 group 内的所有基准测试,第 2 列是单次迭代用时(单位为纳秒),第 3 列是每秒迭代次数,第 4 列是性能提升倍数,以第一个基准测试为基准。

基本定义 | Documents for Coost

https://coostdocs.github.io/cn/co/def/

include: co/def.h.
#typedefs #定长整数类型 co/def.h 定义了如下的 8 种整数类型:
typedef int8_t int8; typedef int16_t int16; typedef int32_t int32; typedef int64_t int64; typedef uint8_t uint8; typedef uint16_t uint16; typedef uint32_t uint32; typedef uint64_t uint64; 这些类型在不同平台的长度是一致的,不存在可移植性问题。Google Code Style 建议除了 int,不要使用 short, long, long long 等内置整数类型。
#macros #整型最大、最小值 MAX_UINT8 MAX_UINT16 MAX_UINT32 MAX_UINT64 MAX_INT8 MAX_INT16 MAX_INT32 MAX_INT64 MIN_INT8 MIN_INT16 MIN_INT32 MIN_INT64 这些宏分别表示 8 种整数类型的最大、最小值。
#DISALLOW_COPY_AND_ASSIGN 这个宏用于禁止 C++ 类中的拷贝构造函数与赋值操作。
示例 class T { public: T(); DISALLOW_COPY_AND_ASSIGN(T); }; #__arch64, __arch32 64位系统上,__arch64 定义为 1;32位系统上,__arch32 定义为 1。

简介 | Book for CO

https://idealvin.github.io/cn/about/co/

#CO 是什么 CO 是一个优雅、高效的 C++ 基础库,支持 Linux, Windows 与 Mac 等平台,它实现了类似 golang 的协程、基于协程的网络编程框架、命令行参数与配置文件解析库、高性能日志库、单元测试框架、JSON 库等一系列高质量的基础组件。
CO 在 github 上以 MIT 许可证开源,它使用了部分三方代码,可能有不同的许可证,详情见 LICENSE 文件。为了方便国内用户,gitee 上也会定期同步 github 上的代码。
#CO 的发展历程 Alvin(idealvin) 自 2013 年开始开发 CO,最初的目的是为了减少 C++ 项目中的三方依赖,同时提高 C++ 的开发效率。从 2015 年开始,Alvin 将 CO 引入实际项目中,供自己与同事使用,大大缩减了项目的开发周期,CO 也得以经受工业项目的检验。
经过多年的积累、沉淀,到 2019 年,Alvin 又用 C++ 实现了 golang 中的协程机制,并提供了一套基于协程的网络编程框架。CO 协程诞生之初,就被用于嵌入式网络程序开发,并取得了立竿见影的效果。
截至 2021 年,CO 协程又有了长足的发展,目前在 Linux/Windows/Mac 平台均已支持 hook,并且实现了协程锁、协程同步事件、协程池以及 golang 中的 channel 与 waitgroup,用户可以用 CO 写出 golang 的体验。
#快速上手 #编译 建议安装 xmake,在 CO 根目录执行如下命令构建所有子项目:

defer | Documents for CO

https://idealvin.github.io/en/co/defer/

include: co/defer.h.
#defer defer is a macro provided by CO, which is similar to defer in golang.
#include "co/defer.h"#include "co/time.h"#include "co/log.h"#include "co/json.h" void f(const Json& req, Json& res) { Timer t; LOG << "req: " << req; defer(LOG << "res: " << res << ", time elapse: " << t.us() << "us"); // do something here } In the above example, the code in defer will be executed at the end of the function f, thus printing the output and time elapse of the function.

编译 | Book for CO

https://idealvin.github.io/cn/co/build/

#编译器要求 各平台需要安装的编译器如下:
Linux: gcc 4.8+ Mac: clang 3.3+ Windows: vs2015+ #xmake CO 推荐使用 xmake 作为构建工具。
#安装 xmake windows, mac 与 debian/ubuntu 可以直接去 xmake 的 release 页面下载安装包,其他系统请参考 xmake 的 Installation 说明。
xmake 在 linux 上默认禁止 root 用户编译,ruki 说不安全,可以在 ~/.bashrc 中加上下面的一行,启用 root 编译:
export XMAKE_ROOT=y #设置 xmake github 镜像代理 xmake 可能会从 github 上拉取三方库,国内 github 下载速度较慢,可以用下面的方式设置镜像代理:
安装 xmake 2.5.4 以上版本。 执行 xmake show -l envs 命令查找 XMAKE_GLOBALDIR,在该环境变量指向的目录下面创建一个 pac.lua 文件,在文件里加上下面的代码: function mirror(url) return url:gsub("github.

co/log | Book for CO

https://idealvin.github.io/en/co/log/

include: co/log.h.
#Basic introduction co/log is a C++ streaming log library similar to google glog, which prints logs like this:
LOG << "hello world" << 23; co/log divides logs into five levels: debug, info, warning, error, fatal, and provides a series of macros for printing logs of different levels. Printing the fatal level log will terminate the program, and co/log will also print the stack information before the program exits.

TCP | Book for CO

https://idealvin.github.io/en/co/net/tcp/

include: co/so/tcp.h.
#tcp::Connection tcp::Connection is a simple encapsulation of TCP connection, it is designed for TCP server. When SSL is enabled in a TCP server, tcp::Connection will use SSL to transmit data.
#Connection::Connection Connection(sock_t s); Constructor, the parameter s is the socket descriptor. #Connection::~Connection Connection::~Connection(); Destructor, call close() to close the connection. #Connection::close virtual int close(int ms = 0); Close the connection. When the parameter ms > 0, close the connection after a certain delay.

Timed task scheduler | Book for CO

https://idealvin.github.io/en/co/tasked/

include: co/tasked.h.
#Tasked The Tasked class is a simple timed task scheduler. All tasks are scheduled internally by a single thread, but tasks can be added from any thread. When a task is blocked, it will affect all subsequent tasks. Therefore, it is not recommended to use Tasked to schedule tasks that may block for a long time.
#Tasked::Tasked Tasked(); Tasked(Tasked&& t); The first version is the default constructor. When the object is created, the scheduling thread will start.

JSON | Book for CO

https://idealvin.github.io/cn/co/json/

include: co/json.h.
co/json 是一个类似 rapidjson 的 json 库,与 rapidjson 相比,它既有一定的性能优势,同时又更简单易用。
最新版本的实现中,将 json 对象构建到一块连续的内存上,大大减少了内存分配操作,json 的 parsing 速度也有了显著提升,实测可以超过 rapidjson 的两倍。由于一个 json 对象就是一块连续的内存,拷贝起来很容易,因此移除了早期版本中使用的引用计数。
#基本概念 #JSON 数据格式 JSON 是一种简单的数据格式,它支持两种数据结构:
由一系列 key/value 键值对构成的集合,这类结构称为 object,对应编程语言中的 struct, map 等等。 由一系列 value 构成的列表,这类结构称为 array,对应编程语言中的 vector, list 等等。 上述 key 是 string,value 一般也称为 JSON value,可以是 object, array, number, string, bool(false, true), null 中的任意一种。number 是整数或浮点数,大部分实现会将整数与浮点数区分开。
object 由一对大括号括起来,array 由一对中括号括起来,它们看起来像下面这样:
{"a":1, "b":false, "s":"xxx"} [1, 3.14, true, "xxx"] 由定义 object 与 array 可以嵌套,从而可以表示树等复杂数据结构。

wait group | Documents for Coost

https://coostdocs.github.io/cn/co/concurrency/coroutine/wg/

include: co/co.h.
#co::wait_group co::wait_group 类似于 golang 中的 sync.WaitGroup,可用于等待协程或线程的退出。
#constructor 1. explicit wait_group(uint32 n); 2. wait_group(); 3. wait_group(wait_group&& wg); 4. wait_group(const wait_group& wg); 1, 将内部计数器初始化为 n。 2, 默认构造函数,将内部计数器初始化为 0。 3, 移动构造函数。 4, 拷贝构造函数,仅将内部引用计数加 1。 #add void add(uint32 n=1) const; 将内部计数器加 n,n 默认为 1。 #done void done() const; 将内部计数器减 1。 #wait void wait() const; 等待直到内部计数器的值变为 0。 #代码示例 #include "co/co.h" #include "co/cout.h" DEF_uint32(n, 8, "coroutine number"); int main(int argc, char** argv) { flag::parse(argc, argv); co::wait_group wg; wg.

配置项 | Documents for Coost

https://coostdocs.github.io/cn/co/concurrency/coroutine/conf/

#配置 Coost 使用 co.flag 定义了协程相关的配置项,配置详细用法请参考 co.flag 文档。
#co_hook_log DEF_bool(co_hook_log, false, ">>#1 print log for API hooks"); 打印 API hook 相关的日志,默认为 false。 v3.0.1 中将配置项 hook_log 重命名为 co_hook_log。 #co_sched_log DEF_bool(co_sched_log, false, ">>#1 print logs for coroutine schedulers"); 打印协程调度相关的调试日志,默认为 false。 v3.0.1 将配置项 co_debug_log 重命名为 co_sched_log。 #co_sched_num DEF_uint32(co_sched_num, os::cpunum(), ">>#1 number of coroutine schedulers"); 协程调度线程的数量,默认为系统 CPU 核数。目前的实现中,这个值最大也是系统 CPU 核数。 #co_stack_num DEF_uint32(co_stack_num, 8, ">>#1 number of stacks per scheduler, must be power of 2"); v3.0.1 新增,每个协程调度器的共享协程栈数量,该值必须是 2 的幂,默认为 8。 #co_stack_size DEF_uint32(co_stack_size, 1024 * 1024, ">>#1 size of the stack shared by coroutines"); 协程栈大小,默认为 1M。

JSON | Documents for CO

https://idealvin.github.io/en/co/json/

include: co/json.h.
co/json is a JSON library similar to rapidjson. Compared with rapidjson, it has certain performance advantages and is easier to use.
In the latest version, a JSON is built into a contiguous memory, which greatly reduces memory allocations. The parsing speed has also been significantly improved, which can be twice faster as rapidjson. Since a JSON object is a contiguous piece of memory, it is easy to copy, so reference counting used in earlier versions is removed.

channel | Documents for Coost

https://coostdocs.github.io/cn/co/concurrency/coroutine/chan/

include: co/co.h.
#co::chan template class chan; co::chan 是一个模板类,它类似于 golang 中的 channel,用于在协程之间传递数据。
从 v3.0.1 开始,co::chan 可在协程或非协程中使用,且可存储 std::string 等非 POD 类型的值。 #constructor 1. explicit chan(uint32 cap=1, uint32 ms=(uint32)-1); 2. chan(chan&& c); 3. chan(const chan& c); 1, 参数 cap 是内部队列的最大容量,默认是 1,参数 ms 是读写操作的超时时间,单位为毫秒,默认为 -1,永不超时。 2, 移动构造函数。 3, 拷贝构造函数,仅将内部引用计数加 1。 #close void close() const; 关闭 channel,关闭后 channel 不可写,但可读。 #done bool done() const; 判断读、写操作是否成功完成。 #operator bool explicit operator bool() const; 若 channel 为关闭状态,返回 false,否则返回 true。 #operator« chan& operator<<(const T& x) const; chan& operator<<(T&& x) const; 写入元素 x。 此方法会阻塞,直到写入操作完成或超时。可以调用 done() 方法判断写操作是否成功完成。 若 channel 已关闭,写操作会失败,此方法立即返回。 #operator» chan& operator>>(T& x) const; 读取元素。 此方法会阻塞,直到读取操作完成或超时。可以调用 done() 方法判断读操作是否成功完成。 若 channel 已关闭且 channel 中无元素可读时,读操作会失败,此方法立即返回。 #代码示例 #include "co/co.

内存分配 | Documents for Coost

https://coostdocs.github.io/cn/co/mem/

include: co/mem.h.
#co::alloc 1. void* alloc(size_t size); 2. void* alloc(size_t size, size_t align); 1, 分配 size 字节的内存。 2, 分配 size 字节的内存,内存边界是 align 字节对齐的(align <= 1024)。 第 2 个版本中,align 必须是 2 的幂,且不能超过 1024。 #co::free void free(void* p, size_t size); 释放 co::alloc 或 co::realloc 分配的内存,size 是所分配内存的大小。 co::free 不同于系统提供的 ::free,需要额外带上一个 size 参数。 #co::realloc void* realloc(void* p, size_t old_size, size_t new_size); 重新分配内存,old_size 是之前的内存大小,new_size 是新的大小,后者必须大于前者。 #co::zalloc void* zalloc(size_t size); 分配 size 字节的内存,并将内存清零。 #———— #co::make template<typename T, typename.

Thread | Documents for CO

https://idealvin.github.io/en/co/thread/

include: co/thread.h.
#Thread The Thread class is an encapsulation of the thread. When a Thread object is created, the thread will be started. Once the thread is started, it will run until the thread function exits. The Thread class does not provide a method for forcing terminating the thread (something like pthread_cancel). This type of method is usually unsafe and may cause damage to user data.
#Thread::Thread explicit Thread(co::Closure* cb); template explicit Thread(F&& f); template<typename F, typename P> Thread(F&& f, P&& p); template<typename F, typename T, typename P> Thread(F&& f, T* t, P&& p); Constructor, the thread will start after the Thread object is created.

互斥锁 | Documents for Coost

https://coostdocs.github.io/cn/co/concurrency/coroutine/mutex/

include: co/co.h.
#co::mutex 从 v3.0.1 开始,co::mutex 可以在协程与非协程中使用。 #constructor 1. mutex(); 2. mutex(mutex&& m); 3. mutex(const mutex& m); 1, 默认构造函数。 2, 移动构造函数。 3, 拷贝构造函数,仅将内部引用计数加 1。 #lock void lock() const; 获取锁,阻塞直到获得锁为止。 #try_lock bool try_lock() const; 获取锁,不会阻塞,成功获取锁时返回 true,否则返回 false。 #unlock void unlock() const; 释放锁,一般由之前获得锁的协程或线程调用。 #co::mutex_guard #constructor explicit mutex_guard(co::mutex& m); explicit mutex_guard(co::mutex* m); 构造函数,调用 m.lock() 获取锁,参数 m 是 co::mutex 类的引用或指针。 #destructor ~mutex_guard(); 析构函数,释放构造函数中获得的锁。 #代码示例 #include "co/co.h" #include "co/cout.h" co::mutex g_m; int g_v = 0; void f() { co::mutex_guard g(g_m); ++g_v; } int main(int argc, char** argv) { flag::parse(argc, argv); go(f); go(f); f(); f(); co::sleep(100); co::print("g_v: ", g_v); return 0; }

Atomic Operations | Documents for CO

https://idealvin.github.io/en/co/atomic/

include: co/atomic.h.
#Arithmetic operations #atomic_inc template inline T atomic_inc(T* p); Atomic increment, T is any integer type with a length of 1, 2, 4, 8 bytes, and the parameter p is a pointer of type T.
This function performs an increment operation on the integer pointed to by p and returns the result after increment.
Example
int i = 0; uint64 u = 0; int r = atomic_inc(&i); // i -> 1, r = 1 uint64 x = atomic_inc(&u); // u -> 1, x = 1 #atomic_fetch_inc template inline T atomic_fetch_inc(T* p); The same as atomic_inc, but returns the value before increment.

单元测试框架 | Book for CO

https://idealvin.github.io/cn/co/unitest/

include: co/unitest.h.
#基本概念 co/unitest 是一个单元测试框架,与 google gtest 类似,但更简单易用。
#测试单元与测试用例 一个测试程序可以按功能或模块划分为多个测试单元,每个测试单元下面可以有多个测试用例。如可以给 C++ 中的一个类(或模块)定义一个测试单元,类(或模块)中的每个方法定义一个测试用例。
在 co/unitest 中,定义一个测试单元时,会生成一个类,类中有一个 run() 方法,所有的测试用例代码都在 run() 方法里面。co/unitest 几乎屏蔽了所有的细节,用户看不到类,甚至看不到 run() 方法,可以完全专注于写测试代码:
DEF_test(test_name) { DEF_case(a) { // write test code here } DEF_case(b) { // write test code here } } 上面的 DEF_test 实际上就是实现了类中的 run() 方法,DEF_case 则定义了测试用例,一个测试用例就相当于 run() 方法中的一个代码块,连函数都不是。
#DEF_test #define DEF_test(name) \ DEF_bool(name, false, "enable this test if true."); \ ... \ void UTest##name::run() DEF_test 宏用于定义测试单元,参数 name 是测试单元的名字。 宏的第一行定义了一个 bool 类型的 flag 变量,是该测试单元的开关。如 DEF_test(os) 定义了一个测试单元 os,命令行参数中可以用 -os 指定运行 os 中的测试代码 宏中间省略的代码,实际上定义了一个类,最后一行定义类中的方法 run(),需要用户完成 run() 方法的函数体。 #DEF_case #define DEF_case(name) _current_case.

协程池 | Documents for Coost

https://coostdocs.github.io/cn/co/concurrency/coroutine/pool/

include: co/co.h.
#co::pool co::pool 是一种通用的协程池,它是协程安全的,内部存储 void* 类型的指针,可以用作连接池、内存池或其他用途的缓存。
#constructor 1. pool(); 2. pool(pool&& p); 3. pool(const pool& p); 4. pool(std::function<void*()>&& ccb, std::function<void(void*)>&& dcb, size_t cap=(size_t)-1); 1, 默认构造函数,与 4 相比,ccb 与 dcb 为 NULL。
2, 移动构造函数。
3, 拷贝构造函数,仅将内部引用计数加 1。
4, 参数 ccb 用于创建元素,参数 dcb 用于销毁元素,参数 cap 指定 pool 的最大容量,默认为 -1,不限容量。
注意参数 cap 并不是总容量,它是对单个线程而言,在 co::pool 内部实现中,每个线程都有自己的 pool,如 cap 设置为 1024,调度线程有 8 个,则总容量是 8192。
当 dcb 为 NULL 时,参数 cap 会被忽略,这是因为当元素个数超过最大容量时,co::pool 需要用 dcb 销毁多余的元素。

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.