async_simple 诞生于阿里巴巴智能引擎事业部,目前广泛应用于图计算引擎、时序数据库、搜索引擎等在线系统。
快速开始
通过计算一个文档中特定字符数量的 demo 程序来介绍如何使用 Lazy 进行编程。创建空文件 CountChar.cpp, 并填入以下内容:
#include <algorithm>
#include <fstream>
#include <iostream>
#include <string>
#include <vector>
#include "async_simple/coro/Lazy.h"
#include "async_simple/coro/SyncAwait.h"
using namespace async_simple::coro;
using Texts = std::vector<std::string>;
Lazy<Texts> ReadFile(const std::string &filename) {
Texts Result;
std::ifstream infile(filename);
std::string line;
while (std::getline(infile, line))
Result.push_back(line);
co_return Result;
}
Lazy<int> CountLineChar(const std::string &line, char c) {
co_return std::count(line.begin(), line.end(), c);
}
Lazy<int> CountTextChar(const Texts &Content, char c) {
int Result = 0;
for (const auto &line : Content)
Result += co_await CountLineChar(line, c);
co_return Result;
}
Lazy<int> CountFileCharNum(const std::string &filename, char c) {
Texts Contents = co_await ReadFile(filename);
co_return co_await CountTextChar(Contents, c);
}
int main() {
int Num = syncAwait(CountFileCharNum("file.txt", 'x'));
std::cout << "The number of 'x' in file.txt is " << Num << "n";
return 0;
}
同时执行命令:
base64 /dev/urandom | head -c 10000 > file.txt
这个命令会在 file.txt 中随机生成大小为 10000 字节的文本文件。之后编译并执行:
clang++ -std=c++20 CountChar.cpp -o CountChar
./CountChar
之后 CountChar 会计算出 file.txt 中 x 的数量。至此,我们就完成了一个使用协程计算文本字符数量的程序了。
使用 Lazy
想要使用 Lazy,需要先 #inlude <async_simple/coro/Lazy.h>, 再实现一个返回类型为 Lazy
#include <async_simple/coro/Lazy.h>
Lazy<int> task1(int x) {
co_return x; // 带有 co_return 的函数是协程函数。
}
在 Lazy 中也可以 co_await 其他 awaitable 对象:
#include <async_simple/coro/Lazy.h>
Lazy<int> task2(int x) {
co_await std::suspend_always{};
co_return x; // 带有 co_return 的函数是协程函数。
}
工具类示例-协程锁
「Spin Lock」Lazy 无栈协程版本自旋锁在机制上类似,但是当前协程持续无法获取到锁时,当前协程会被重新调度以避免长时间自旋阻塞当前线程上其他协程。
协程版用法
#include <async_simple/coro/SpinLock.h>
SpinLock lock;
Lazy<> doSomething() {
co_await lock.coLock();
// critical section
lock.unlock();
co_return;
}
Lazy<> doSomethingV2() {
// ...
{
auto scope = co_await lock.coScopedLock();
// critical section
}
co_return;
}
线程版用法
线程版会使得当前线程死等,尽量避免在协程环境中使用。
#include <async_simple/coro/SpinLock.h>
SpinLock lock;
void doSomething() {
lock.lock();
// critical section
lock.unlock();
co_return;
}
void doSomethingV2() {
ScopedSpinLock scope(lock);
// critical section
co_return;
}
控制自旋
尽管协程版自旋锁长时间获取不到锁会主动让出。但是重新调度会使得获取锁时间变得更加不确定,这取决于 Executor 调度行为。当临界区范围过大时,频繁让出可能引起性能下降。此时可以增大自旋次数来减少协程主动让出频率。
#include <async_simple/coro/SpinLock.h>
SpinLock lock(2048); // Spin Count
Lazy<> doSomething() {
co_await lock.coLock();
// critical section
lock.unlock();
}
准备环境
Debian/Ubuntu 系列
-
安装 clang11 及其以上版本。 -
安装 cmake 或 bazel -
如需使用 libaio 功能,需安装 libaio。
sudo apt install libaio-dev -y
# Install cmake
sudo apt install cmake -y
# Install bazel See: https://bazel.build/install/ubuntu
使用 apt 安装 gtest、gmock
sudo apt install -y libgtest-dev libgmock-dev
CentOS/Fedora 系列
-
同样是先安装 clang11 及其以上版本。 -
安装 cmake 或 bazel、libaio(可选)。
# Optional.
sudo yum install cmake libaio-devel -y
# Install bazel See: https://bazel.build/install/redhat
使用 yum 安装 gtest、gmock
sudo yum install gtest-devel gmock-devel
源码编译安装 gtest、gmock
git clone git@github.com:google/googletest.git -b v1.8.x
cd googletest
mkdir build && cd build
cmake .. && sudo make install
Windows
# Install cmake
winget install cmake
# Install google-test
# TODO
# Install bazel See: https://bazel.build/install/windows
Docker 编译环境
# 使用 centos-7
git clone https://github.com/alibaba/async_simple.git
cd async_simple/docker/centos7
docker build . --no-cache -t async_simple:1.0 --network host
docker run -it --name test-async-simple async_simple:1.0 /bin/bash
// 已经进入 centos bash shell
mkdir build && cd build
cmake3 .. -DCMAKE_BUILD_TYPE=Release
# 使用 ubuntu 22.04
git clone https://github.com/alibaba/async_simple.git
cd async_simple/docker/ubuntu
docker build . --no-cache -t async_simple:1.0 --network host
docker run -it --name test-async-simple async_simple:1.0 /bin/bash
// 已经进入 ubuntu bash shell
mkdir build && cd build
# 使用 clang 编译
CXX=clang++-13 CC=clang-13 cmake .. -DCMAKE_BUILD_TYPE=Release
# 使用 g++ 编译
CXX=g++-11 CC=gcc-11 cmake .. -DCMAKE_BUILD_TYPE=Release
传送门
开源协议:Apache-2.0 license
开源地址:https://github.com/alibaba/async_simple
-END-
原文始发于微信公众号(开源技术专栏):阿里开源的轻量级 C++ 异步框架
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/166586.html