基于以下内容,C ++ 20中的协程看起来像是无堆栈的。
https://en.cppreference.com/w/cpp/language/coroutines
我担心的原因有很多:
使用无堆栈协程时,只有顶层例程可以被挂起。该顶级例程调用的任何例程本身都不会暂停。这禁止在通用库中的例程中提供挂起/恢复操作。
由于需要自定义分配器和内存池,因此代码更加详细。
如果任务等待操作系统为它分配一些内存(没有内存池),则速度较慢。
鉴于这些原因,我真的希望我对当前的协程是错误的。
问题分为三个部分:
协程状态是通过非数组运算符new在堆上分配的。 https://en.cppreference.com/w/cpp/language/coroutines
编辑:
我现在正在为协程进行cppcon讨论,如果我对自己的问题有任何答案,我将其发布(到目前为止没有任何内容)。
CppCon 2014:Gor Nishanov“等待2.0:无堆栈可恢复函数”
https://www.youtube.com/watch?v=KUhSjfSbINE
CppCon 2016:James McNellis“ C ++协程简介”
背景
我有个任务类型既可以co_return和co_yield。在 LLVM 中,任务按预期工作并通过了一些早期测试。在 MSVC 和 GCC 中,代码以相同的方式失败(巧合?)。
简要问题
具有以下测试功能:
Task<int> test_yielding()
{
co_yield 1;
co_return 2;
}
Run Code Online (Sandbox Code Playgroud)
从 Task 对象中检索了两个值。
auto a = co_await fn;
auto b = co_await fn;
Run Code Online (Sandbox Code Playgroud)
a 的值预期为 1,b 的值预期为 2。
结果针对 进行测试a + b == 3。
上面的测试通过了,但是下面的测试失败了:
auto res = co_await fn + co_await fn
Run Code Online (Sandbox Code Playgroud)
GCC 和 MSVC 的 res 值为 4。两者都是从最终的 co_return 中检索到的。据我了解,第一次和第二次调用的co_await fn顺序应该是 1 和 2。
在 MSVC 和 GCC 中,代码失败,因为它们似乎重新排序await_resume,return_value …
什么
我收到一条错误消息,我找不到任何信息,是否有人知道我在哪里可以找到有关ld 253退出状态的任何信息?我什么都找不到.谷歌只有一个提及,它看似无关,没有解决方案.
size
对于链接器和编译器的详细输出,没有其他警告或错误甚至模糊地与上述相关.
试图找到问题
该错误在某种程度上与程序大小有关,但程序尚未达到系统闪存大小,所以我有点困惑.
如果我运行大小,则结果如下(设备限制为64K):
text data bss dec
45608 396 6200 52204
Run Code Online (Sandbox Code Playgroud)
当我将设备内存大小增加到128K时没有任何变化,相同的消息......但是,如果我将代码大小减少到大约54 K以下程序编译,我删除哪个代码无关紧要.
如果我只添加一点代码,二进制文件的大小应该只增加几百个字节.但是,当我这样做时,链接器失败并出现上述错误.
在检查从objcopy创建的二进制文件时,内存中有一个巨大的空白区域,内存肯定不是满的.链接器文件已附加但我不知道它们是如何导致我的问题的:
删除链接以支持在问题中包含链接器文件.
更新
问题仍然存在,但我注意到在生成的映射文件中它似乎停在一个模板对象的中间,就好像链接器只是抛出一些异常并中止.它停在的行是相当繁重的模板代码,但它确实实例化它崩溃的确切事物(或者至少类似的对象,唯一的区别是捕获的lambda类型,它们总是按照标准的唯一类型).
映射文件中的最后一项是0x080008ce,并且因为闪存从地址0x08000000开始,这实际上是0x08ce,这远远不及闪存的末尾.
sections.ld
/*
* Default linker script for Cortex-M (it includes specifics for STM32F[34]xx).
*
* To make use of the multi-region initialisations, define
* OS_INCLUDE_STARTUP_INIT_MULTIPLE_RAM_SECTIONS for the _startup.c file.
*/
/*
* The '__stack' definition is required by crt0, do not remove it.
*/
__stack = ORIGIN(RAM) + LENGTH(RAM);
_estack = __stack; /* STM specific definition …Run Code Online (Sandbox Code Playgroud) 这里的目标是帮助人们在使用 C++ 进行开发时捕获嵌入式系统上的一些错误。作为其中的一部分,我试图让 clang-tidy 适合小型嵌入式目标。
我正在尝试设置 CMake 来执行以下操作:
但是,clang-tidy 失败并显示“未知目标 CPU 'armv6-m”
--
我使用的CMake脚本如下:
ClangTidy.cmake
set(ENABLE_CLANG_TIDY ON CACHE BOOL "Add clang-tidy automatically to builds")
if (ENABLE_CLANG_TIDY)
find_program(CLANG_TIDY_EXE NAMES "C:\\Program Files\\LLVM\\bin\\clang-tidy.exe")
if (CLANG_TIDY_EXE)
message(STATUS "clang-tidy found: ${CLANG_TIDY_EXE}")
set(CLANG_TIDY_CHECKS "-*,modernize-*")
set(CMAKE_CXX_CLANG_TIDY "${CLANG_TIDY_EXE};-checks=${CLANG_TIDY_CHECKS};-header-filter='${CMAKE_SOURCE_DIR}/*'"
CACHE STRING "" FORCE)
else()
message(AUTHOR_WARNING "clang-tidy not found!")
set(CMAKE_CXX_CLANG_TIDY "" CACHE STRING "" FORCE) # delete it
endif()
endif()
Run Code Online (Sandbox Code Playgroud)
armv6-m 是 CMake 脚本的一部分,但它仅用于 GCC,并使用以下命令来设置 GCC 标志:
set(TARGET STM32F070x6)
set(ARCH armv6-m)
set(CORE cortex-m0) …Run Code Online (Sandbox Code Playgroud) 比较 MSVC、clang 和 GCC 中生成的程序集时。MSVC 程序集似乎比 Clang 代码差得多。
问题
GCC 和 MSVC 中是否有一个必需的标志来生成等效的程序集,或者在这种特定情况下 Clang 更好。我尝试了各种 MSVC 标志(不同的 /O 标志),但没有发生实质性变化。
或者我的代码是否有变化,可以让编译器实现更好的优化。我尝试过改变代码而不丢失基本结构也没有改变。
代码
我正在编译的代码只有 26 行,所以这里是:
#include <cstdint>
#include <type_traits>
template <typename A, typename B>
struct BitCast
{
static_assert(std::is_pod<A>(), "BitCast<A, B> : A must be plain old data type.");
static_assert(std::is_pod<B>(), "BitCast<A, B> : B must be plain old data type.");
static_assert(sizeof(A) == sizeof(B), "BitCast<A, B> : A and B must be the same size.");
static_assert(alignof(A) == alignof(B), "BitCast<A, B> : A and …Run Code Online (Sandbox Code Playgroud) 背景
\n\n在确信C++ 无堆栈协程非常棒之后。我一直在为我的代码库实现协程,并意识到 Final_Suspend 中的一个奇怪之处。
\n\n语境
\n\n让\xe2\x80\x99s 假设你有以下final_suspend函数:
\n\nfinal_awaitable final_suspend() noexcept\n{\n return {};\n}\nRun Code Online (Sandbox Code Playgroud)\n\n并且,final_awaitable的实现如下:
\n\nstruct final_awaitable\n{\n bool await_ready() const noexcept\n {\n return false;\n }\n default_handle_t await_suspend( promise_handle_t h ) const noexcept\n { \n return h.promise().continuation();\n }\n void await_resume() const noexcept {}\n};\nRun Code Online (Sandbox Code Playgroud)\n\n如果这里的延续是从任务队列中原子检索的,并且任务队列可能为空(这可能发生在await_ready和await_suspend之间的任何时间),那么await_suspend必须能够返回一个空白延续。
\n\n据我了解,当await_suspend返回句柄时,返回的句柄立即恢复(N4775草案中的5.1)。因此,如果此处没有可用的延续,则任何应用程序都会崩溃,因为在从wait_suspend接收到无效的协程句柄后,会在无效的协程句柄上调用恢复。
\n\n以下是执行顺序:
\n\nfinal_suspend Constructs final_awaitable.\n final_awaitable::await_ready Returns false, …Run Code Online (Sandbox Code Playgroud) 在C++标准草案中:
其中提到了这些术语import-keyword、module-keyword和export-keyword。
在语法部分,我不太确定按照A.1 概述如何可能
“此处描述的语法接受有效 C++ 结构的超集。”
本附录中似乎没有定义这些语法。
可以在这里解决:
4 在 pp-import 的所有三种形式中,导入和导出(如果存在)预处理标记分别替换为 import-keyword 和 export-keyword 预处理标记。
但我真的不知道这在语法方面意味着什么......这是什么意思?
一些相关的语法在这里(希望我可以帮助某人获得必要的信息,而不必遍历标准)。
preprocessing-token:
header-name
import-keyword
module-keyword
export-keyword
identifier
pp-number
character-literal
user-defined-character-literal
string-literal
user-defined-string-literal
preprocessing-op-or-punc
each non-whitespace character that cannot be one of the above
Run Code Online (Sandbox Code Playgroud)
keyword:
any identifier listed in Table 5
import-keyword
module-keyword
export-keyword
Run Code Online (Sandbox Code Playgroud)
module-import-declaration:
import-keyword module-name attribute-specifier-seqopt ;
import-keyword module-partition …Run Code Online (Sandbox Code Playgroud) c++ ×7
c++20 ×4
assembly ×1
asynchronous ×1
clang ×1
clang-tidy ×1
cmake ×1
embedded ×1
gcc ×1
ld ×1
visual-c++ ×1