为什么从主线程调用时`std::promise::set_value` 会抛出错误?

Isa*_*old 6 c++ multithreading c++-standard-library

当我运行以下代码时,

#include <future>

int main()
{
    std::promise<int> p;
    p.set_value(1);
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

std::system_error被抛出。但是,当我在另一个线程中设置 promise 的值时,

#include <future>
#include <thread>

int main()
{
    std::promise<int> p;
    std::thread([&]{p.set_value(1);}).join();
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

一切正常。根据我的理解std::promise,调用set_value不应该抛出异常,除非 promise 没有共享状态(即它已被移出)或者已经为其分配了值,即使那样它也会抛出std::future_error,而不是std::system_error。由于没有数据竞争或任何类似的情况,因此我是set_value从创建承诺的线程还是在另一个线程中调用都无关紧要。有什么我想念的吗?

我已经使用g++clang尝试过这个,结果相同。具体来说,当我在顶部运行代码时,以下输出到stderr

terminate called after throwing an instance of 'std::system_error'
  what():  Unknown error -1
Aborted (core dumped)
Run Code Online (Sandbox Code Playgroud)

这些命令用于编译顶部的代码,

g++ main_thread.cpp -o main_thread -std=c++17 -g -Og
clang main_thread.cpp -o main_thread -std=c++17 -lstdc++

Run Code Online (Sandbox Code Playgroud)

这些用于编译底部的代码:

g++ separate_thread.cpp -o separate_thread -lpthread -std=c++17 -g -Og
clang separate_thread.cpp -o separate_thread -std=c++17 -lstdc++ -lpthread
Run Code Online (Sandbox Code Playgroud)

Woo*_*ord 4

std::promise是线程支持库的一部分,因此它需要在编译器选项中启用线程支持(例如-pthread)。

请注意,这-pthread会影响编译和链接阶段。从man g++

-pthread
使用 pthreads 库添加对多线程的支持。该选项为预处理器和链接器设置标志。