阿里开源的轻量级 C++ 异步框架

async_simple 诞生于阿里巴巴智能引擎事业部,目前广泛应用于图计算引擎、时序数据库、搜索引擎等在线系统

阿里开源的轻量级 C++ 异步框架

快速开始

通过计算一个文档中特定字符数量的 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

(0)
小半的头像小半

相关推荐

发表回复

登录后才能评论
极客之音——专业性很强的中文编程技术网站,欢迎收藏到浏览器,订阅我们!