不积小流,无以成江海

海纳百川,有容乃大

参考 tnie/learn_xxx 中 coro 项目。

如果想看懂 asio 如何支持 co_await 的,想更细致地用好协程,就需要了解更基础(同时也是更复杂的)内容。

第一章

微软专家 C++ coroutines: Getting started with awaitable objects 开篇的陈述,比我的倾向更具说服力:

Coroutines were added to C++20, and Lewis Baker has a nice introduction to them.

特别推荐这几篇文章,作者写了 cppcoro 库,牛人!

首推,此系列的文章作为入门。

对协程介绍时,先介绍 awaitable/awaiterpromise。学习笔记/摘抄,见 coroutine-a~c.md

阅读全文 »

来源:https://lewissbaker.github.io/2018/09/05/understanding-the-promise-type

Coroutine Concepts

The compiler applies some fairly mechanical transformations to the code that you write to turn it into a state-machine that allows it to suspend execution at particular points within the function and then later resume execution.

编译器会对您编写的代码进行一些相当机械的转换,以将其转换为状态机,使状态机可以在函数内的特定点挂起执行,然后再恢复执行。

Promise objects

The Promise object defines and controls the behaviour of the coroutine itself by implementing methods that are called at specific points during execution of the coroutine.

阅读全文 »

来源:https://lewissbaker.github.io/2017/11/17/understanding-operator-co-await

What does the Coroutines TS give us?

The facilities the C++ Coroutines TS provides in the language can be thought of as a low-level assembly-language for coroutines. These facilities can be difficult to use directly in a safe way and are mainly intended to be used by library-writers to build higher-level abstractions that application developers can work with safely.

C ++ Coroutines TS 提供的功能可以被认为是协程的一种低级汇编语言。这些功能可能很难以安全的方式直接使用,并且主要旨在供库编写人员用来构建更高级的抽象,以便应用程序开发人员可以安全地使用它们。

Compiler <-> Library interaction

Instead, it specifies a general mechanism for library code to customise the behaviour of the coroutine by implementing types that conform to a specific interface. The compiler then generates code that calls methods on instances of types provided by the library.

它为库代码指定了一种通用机制,可通过 实现符合特定接口的类型 来自定义协程的行为。然后编译器调用 这些类型的方法 = 库提供的类型的实例的方法

There are two kinds of interfaces that are defined by the coroutines TS: The Promise interface and the Awaitable interface.

阅读全文 »

来源:https://lewissbaker.github.io/2017/09/25/coroutine-theory

Coroutines

Coroutines generalise the operations of a function by separating out some of the steps performed in the Call and Return operations into three extra operations: Suspend, Resume and Destroy.

比其他文章多描述了一个 Destroy 步骤,更准确。

Note that, like the Return operation of a function, a coroutine can only be suspended from within the coroutine itself at well-defined suspend-points.

请注意,就像函数的 Return 操作一样,协程只能在定义好的暂停点处从协程自身内部暂停。

Coroutine activation frames

With coroutines there are some parts of the activation frame that need to be preserved across coroutine suspension and there are some parts that only need to be kept around while the coroutine is executing. For example, the lifetime of a variable with a scope that does not span any coroutine suspend-points can potentially be stored on the stack.

阅读全文 »

来源:https://blog.panicsoftware.com/co_awaiting-coroutines/

Awaitable

As I have mentioned in the previous posts, the suspend_always and suspend_never are types, that fulfill the Awaitable concept.

We can get the Awaitable object in two ways:

  • Direct creation of Awaitable,
  • Transformation of the object into Awaitable because of await_transform function.

co_await operator and Awaiter

The co_await operator is actually responsible for two things:

  • Forcing compiler to generate some coroutine boilerplate code
  • Creating the Awaiter object.

So first let’s have a look at how is the awaiter object is created. The co_await operator is responsible for the creation of the awaiter object. The co_await operator declaration is looked upon in the awaitable object and if it’s found this co_await operator is executed to obtain awaiter object. Otherwise, if the appropriate function is not found, then awaitable becomes the awaiter.

阅读全文 »

来源:https://blog.panicsoftware.com/your-first-coroutine/

std::future<int> foo();

这是个普通函数,还是协程?这是由其具体实现决定的。

If any of those keywords occur in the function, then it becomes a coroutine.

  • co_await
  • co_return
  • co_yield

So the operator co_await is a unary operator, which takes the Awaitable object as its argument.

Why do we need to define additional types?

So the object used to communicate with the coroutine is the object of the coroutine’s return type.

我们使用协程的返回值,和协程进行沟通。

阅读全文 »

来源:https://blog.panicsoftware.com/coroutines-introduction/

虽然协程作为重要特性,即将进入 C++ 20,但仍然有很多人吐槽。

Main complaints were regarding the hardness to understand, lots of customisation points, and possibly not optimal performance due to possibly unoptimised dynamic memory allocations

主要的抱怨是关于理解起来很难,大量的定制点以及,未优化的动态内存分配可能造成性能的损失。

谷歌的提案存在一些问题,最终被接受的协程方案来自微软。

什么是协程

The coroutines already exist in many programming languages, may it be Python or C#. Coroutines provide one more way to create asynchronous code. How this way differs from threads and why do we need a dedicated language feature for coroutines and finally how we can benefit will be explained in this section.

阅读全文 »

TODO

  1. 蓝牙网络连接,什么作用?删掉或禁用有影响吗?
  2. 如何自动切换网关
  3. 将 共享目录从台式机移到笔记本中,使用网线已经没有带宽限制了。

装机

Windows预先安装环境(英语:Microsoft Windows Preinstallation Environment),简称 Windows PE 或 WinPE,是 Microsoft Windows 的轻量版本。

关于装机的知识,通过 微PE优盘使用说明书 可以学习,虽然我们并不购买他家的优盘。以下摘录部分笔记。

阅读全文 »

std::function<> 模板到底是什么? 可以简单理解为对应 C 语言中的函数指针。入参或绑定的参数如果是原始指针或引用时,需要特别注意其生存周期。

关于函数类模板,学习《Effective.Modern.C++》P39

And maybe now you’re thinking “What’s a std::function object?” So let’s clear that up

boost::empty_value 的意义?

待补充

获得 std::function 对象

Lambda expressions

Constructs a closure: an unnamed function object capable of capturing variables in scope. 摘自 lambda

Function objects

A function object is any object for which the function call operator is defined. 摘自 functional

std::function,推荐查看其 Example

Class template std::function is a general-purpose polymorphic function wrapper. Instances of std::function can store, copy, and invoke any CopyConstructible Callable target – functions, lambda expressions, bind expressions, or other function objects, as well as pointers to member functions and pointers to data members. 摘自 function

需要强调的是 C++ 标准未对 std::bind 表达式的返回类型做出定义,其返回值并不对应我们熟悉的任何类型,但可以直接赋值给 std::function<>

1
2
3
4
5
6
7
8
9
10
std::function<int(int)> func = std::tolower;
std::function<int(int)> lamb = [](int a) { return a; };
std::string str("niel");
std::function<size_t(void)> bind = std::bind(&std::string::size, &str);
std::function<int(int, int)> object = std::plus<int>();
std::function<size_t(const std::string&)> p2mf = &std::string::size;

//std::function<size_t(void)> bind = std::bind(&std::string::size, std::ref(str));
//// 拷贝传参,请务必明白在做什么。also works, but str is copied
//std::function<size_t(void)> bind = std::bind(&std::string::size, str);

模板参数

1
2
3
// ERR,末尾多余的 const 造成报错内容在千里之外
using SENDFUNC = std::function<void(CBD , void const * const , size_t ) const>;
using SENDFUNC = std::function<void(CBD , void const * const , size_t ) /*const*/>;

递归调用

为什么 function<> 对象递归调用自身不能使用 auto?

vc2015 IntelliSence 提示

使用 auto 类型说明符声明的变量不能出现在其自身的初始值设定项中

阅读全文 »

类接口:保持接口的最小化

p207

当我们试图最小化类接口时(在保证完整性的前提下),不得不忽略大量有用的操作。如果一个函数可以简单、优美、高效地实现为一个独立函数时(即实现为非成员函数),就应该将它的实现放在类外。采用这种方式,函数中的错误就不会直接破坏类对象中的数据。p213

如何创建自己的 vector

预留空间 和 std::allocator

注意,我们并不对预留空间中的元素进行初始化。 p329

我们需要处理非常尴尬的情况:数据结构同时包含已初始化数据和未初始化数据。p341

因为内置的数值类型都是小对象,所以可以一律初始化,无需在意开销。但对于自定义类型,初始化要有的放矢。

阅读全文 »
0%