VC ++实现std :: promise

时间:2017-11-17 17:39:06

标签: c++ multithreading visual-studio-2015 visual-studio-2017

我对std :: promise的VC ++实现(Visual Studio 2015和2017)都有一个奇怪的问题。 set_value_at_thread_exit()似乎不像宣传的那样工作 - 或者我误解了标准允许的内容以及标准不允许的内容。以下代码将在clang中编译并运行正常,但在使用VS2015(在第二个块中)或VS2017(在第三个块中)编译时会崩溃:

#include <future>
#include <thread>
#include <iostream>

int main()
{
    {
        std::cout << "Safe version... ";
        std::promise<int> promise;
        auto f = promise.get_future();

        std::thread
        (
            [](std::promise<int> p) 
            { 
                p.set_value(99); 
            }, 
            std::move(promise)
        )
        .detach();

        std::cout << f.get() << std::endl;
    }

    {
        std::cout << "Will crash VS2015... ";
        std::promise<int> promise;
        auto f = promise.get_future();

        std::thread(
            [p{ std::move(promise) }]() mutable 
            { 
                p.set_value_at_thread_exit(99); 
            }
        )
        .detach();

        std::cout << f.get() << std::endl;
    }

    {
        std::cout << "Will crash VS2017... ";
        std::promise<int> promise;
        auto f = promise.get_future();

        std::thread(
            [](std::promise<int> p) 
            { 
                p.set_value_at_thread_exit(99); 
            }, 
            std::move(promise)
        )
        .detach();

        std::cout << f.get() << std::endl;
    }
}

我试图通过慷慨地使用换行符来显示差异。

问题似乎是在MS实现中,lambda函数内的promise对象的析构函数尝试使用“破坏的承诺”来更新共享状态。即使调用了set_value_at_thead_exit()也是异常。但是,这会失败并依次抛出系统错误。它在尝试锁定关联的互斥锁时发生。 如果未调用set_value_at_thread_exit(),则f.get()将按预期抛出future_error。

查看MS实现(VS2017),我发现代码假装检查共享状态是否在线程退出时就绪,但什么也没做。所以我想知道这是一个错误,还是我误解了API,我应该确保承诺的生命周期延伸到线程退出之外。

后者似乎是VS2017在第二个代码块中发生的事情,但在VS2015中却没有 - 可能是由于std :: thread的实现差异?!

如上所述,代码在

中运行良好

clang:http://rextester.com/FEZDS24592
gcc:http://rextester.com/WFKE61563

但在

中崩溃

VS2015中的第二个区块:http://rextester.com/NODVFO14840
和VS2017中的第三个块。这可以在这里测试:http://webcompiler.cloudapp.net/

所以基本上我想知道我是否应该提出一个问题,或者我是不是会自欺欺人,因为我使用的语言都错了?

由于

1 个答案:

答案 0 :(得分:0)

事实证明,xxx_at_thread_exit()在大多数当前实现中都存在问题。有关详细信息,请参阅this visual studio community issue