vmilea/CppAwait

语言: C++

git: https://github.com/vmilea/CppAwait

C ++中的C#async / await。遗留实现,请查看CppAsync!
C# async/await in C++. Legacy implementation, check out CppAsync instead!
README.md (中文)

注意

不再维护此库。所有开发都转移到了CppAsync,这是一个完全重新实现,更高效,更灵活,并且不依赖于Boost.Context。

Sippavait

CppAwait是一个C ++库,它支持以自然(顺序)形式编写异步代码。

它解决了异步API的典型代码流反转。因此 - 您可以使用普通条件,循环和异常处理程序来表达您的异步算法,而不是链接回调,处理状态和错误代码。

目标:更容易编写必须处理滞后网络和文件I / O的响应式应用程序。

怎么运行的

CppAwait提供了一个类似于C#5的await结构(参见MSDN)。在到达await表达式时,C#编译器会自动将方法的其余部分转换为任务延续。在C ++中,可以通过协程(CppAwait在Boost.Context之上实现)实现类似的效果。调用await()将暂停协程,直到相关任务完成。在协程暂停时,该程序可以自由地完成其他工作。

您的程序需要一个运行循环来管理异步操作。

这是一个显示典型库使用的片段。它将一些数据连接并传输到TCP服务器:

ut::Awaitable awt;

tcp::resolver::iterator outEndpoints;
awt = ut::asio::asyncResolve(resolver, query, outEndpoints);
// Suspend coroutine until task has finished
awt.await();

for (auto it = outEndpoints; it != tcp::resolver::iterator(); ++it) {
    tcp::endpoint ep = *it;
    awt = ut::asio::asyncConnect(socket, ep);

    try {
        awt.await();
        break; // connected
    } catch (const std::exception&) {
        // Try next endpoint
    }
}
if (!socket.is_open()) {
    throw SocketError("failed to connect socket");
}

// Write an HTTP request
awt = ut::asio::asyncWrite(socket, request);
awt.await();

// Read response
awt = ut::asio::asyncReadUntil(socket, outResponse, std::string("\r\n"));
awt.await();

Awaitable类是异步操作的通用包装器。所有异步方法都返回Awaitable。它的await()方法产生对主循环的控制,直到Awaitable完成或失败,此时协程恢复。如果操作失败,则抛出相关的异常。请注意,没有返回值 - 必须通过引用传递输出参数(如端点)。

和常规功能一样,Awaitables很容易编写。 awaitAll()/ awaitAny()支持更复杂的模式。

这是下载和存档某些文件的另一个片段。正在归档文件时,下载的文件正在下载:

std::vector<std::string> urls = { ... };

ut::Awaitable awtArchive;

for (std::string url : urls) {
    // Holds fetched document
    std::unique_ptr<std::vector<char> > document;

    ut::Awaitable awtFetch = asyncFetch(url, &document);

    // Doesn't block, instead it yields. The coroutine
    // gets resumed when fetch done or on exception.
    awtFetch.await();

    if (!awtArchive.isNil()) {
        awtArchive.await();
    }
    awtArchive = asyncArchive(std::move(document));
}

包括几个例子。有关经典异步和等待模式之间的直接比较,请参阅stock client。

特征

  • 协同程序,可迭代的生成器
  • 可组合的等待
  • 支持例外
  • 可以适应任何异步API
  • Boost.Asio包装器
  • 可插入任何带有运行循环的程序
  • 堆栈池具有良好的性能
  • 可定制的日志记录
  • 手提

安装

  1. 安装Boost。要使用CppAwait,需要Boost 1.58+ Boost.Context,Boost.Thread和Boost.System编译[*]。快速指南:
  • 下载Boost存档
  • ./bootstrap
  • ./b2 link = static --build-type = minimal --with-context --with-chrono --with-thread --toolset = your-toolset阶段
  1. 安装CMake 2.8+
  2. 构建CppAwait:
  • mkdir build_dir; cd build_dir
  • cmake -G“your-generator”-DBOOST_ROOT =“path-to-boost”“path-to-CppAwait”
  • 开放解决方案/制造

(*)Boost.Chrono还需要在Visual C ++ 2010上编译示例。有一个可选的Flickr示例依赖于OpenSSL。将OpenSSL置于C:\ OpenSSL下,以便在Windows上自动检测。

可移植性

使用以下任何编译器在Windows / Linux上支持该库:

  • Visual C ++ 2010或更高版本
  • GCC 4.6.2或更高版本

Boost.Context包括ARM / MIPS / PowerPC32 / PowerPC64 / X86-32 / X86-64的汇编代码。

移植到其他平台(例如iOS,Android)应该是微不足道的。

作者

Valentin Milea valentin.milea@gmail.com

执照

Copyright 2012-2015 Valentin Milea

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

  http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

本文使用googletrans自动翻译,仅供参考, 原文来自github.com

en_README.md

NOTICE

This library is no longer being maintained. All development has shifted to CppAsync, a complete reimplementation that is more efficient, flexible, and doesn't depend on Boost.Context.

CppAwait

CppAwait is a C++ library that enables writing asynchronous code in a natural (sequential) form.

It solves the code flow inversion typical of asynchronous APIs. So -- instead of chaining callbacks, dealing with state and error codes -- you can use plain conditionals, loops and exception handlers to express your asynchronous algorithm.

The goal: make it easier to write responsive applications that have to deal with laggy network & file I/O.

How it works

CppAwait provides an await construct similar to the one from C# 5 (see MSDN). Upon reaching an await expression the C# compiler automatically transforms the rest of the method into a task continuation. In C++ a similar effect can be achieved through coroutines (which CppAwait implements on top of Boost.Context). Calling await() will suspend a coroutine until the associated task completes. The program is free to do other work while coroutine is suspended.

Your program needs a run loop to manage asynchronous operations.

Here is a snippet showing typical library use. It connects and transfers some data to a TCP server:

ut::Awaitable awt;

tcp::resolver::iterator outEndpoints;
awt = ut::asio::asyncResolve(resolver, query, outEndpoints);
// Suspend coroutine until task has finished
awt.await();

for (auto it = outEndpoints; it != tcp::resolver::iterator(); ++it) {
    tcp::endpoint ep = *it;
    awt = ut::asio::asyncConnect(socket, ep);

    try {
        awt.await();
        break; // connected
    } catch (const std::exception&) {
        // Try next endpoint
    }
}
if (!socket.is_open()) {
    throw SocketError("failed to connect socket");
}

// Write an HTTP request
awt = ut::asio::asyncWrite(socket, request);
awt.await();

// Read response
awt = ut::asio::asyncReadUntil(socket, outResponse, std::string("\r\n"));
awt.await();

The Awaitable class is a generic wrapper for asynchronous operations. All asynchronous methods return an Awaitable. Its await() method yields control to the main loop until the Awaitable completes or fails, at which point the coroutine resumes. If operation failed the associated exception gets thrown. Note there is no return value -- output parameters such as endpoints must be passed by reference.

Awaitables compose easily, just like regular functions. More complex patterns are supported through awaitAll() / awaitAny().

Here is another snippet which downloads and archives some files. While a file is being archived, the next one is being downloaded:

std::vector<std::string> urls = { ... };

ut::Awaitable awtArchive;

for (std::string url : urls) {
    // Holds fetched document
    std::unique_ptr<std::vector<char> > document;

    ut::Awaitable awtFetch = asyncFetch(url, &document);

    // Doesn't block, instead it yields. The coroutine
    // gets resumed when fetch done or on exception.
    awtFetch.await();

    if (!awtArchive.isNil()) {
        awtArchive.await();
    }
    awtArchive = asyncArchive(std::move(document));
}

There are several examples included. See stock client for a direct comparison between classic async and the await pattern.

Features

  • coroutines, iterable generators

  • composable awaitables

  • support for exceptions

  • can adapt any asynchronous API

  • Boost.Asio wrappers

  • pluggable into any program with a run loop

  • good performance with stack pooling

  • customizable logging

  • portable

Installation

  1. Install Boost. To use CppAwait you need Boost 1.58+ with Boost.Context, Boost.Thread and Boost.System compiled [*]. Quick guide:
  • download Boost archive
  • ./bootstrap
  • ./b2 link=static --build-type=minimal --with-context --with-chrono --with-thread --toolset=your-toolset stage
  1. Install CMake 2.8+

  2. Build CppAwait:

  • mkdir build_dir ; cd build_dir
  • cmake -G "your-generator" -DBOOST_ROOT="path-to-boost" "path-to-CppAwait"
  • open solution / make

(*) Boost.Chrono is additionally required to compile the examples on Visual C++ 2010. There is an optional Flickr example which depends on OpenSSL. Place OpenSSL under C:\OpenSSL for automatic detection on Windows.

Portability

The library is supported on Windows / Linux with any of these compilers:

  • Visual C++ 2010 or later
  • GCC 4.6.2 or later

Boost.Context includes assembly code for ARM / MIPS / PowerPC32 / PowerPC64 / X86-32 / X86-64.

Porting to additional platforms (e.g. iOS, Android) should be trivial.

Authors

Valentin Milea valentin.milea@gmail.com

License

Copyright 2012-2015 Valentin Milea

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

  http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.