C++ 有没有办法取消/分离C++;11?

C++ 有没有办法取消/分离C++;11?,c++,c++11,future,C++,C++11,Future,我有以下代码: #include <iostream> #include <future> #include <chrono> #include <thread> using namespace std; int sleep_10s() { this_thread::sleep_for(chrono::seconds(10)); cout << "Sleeping Done\n"; return 3; }

我有以下代码:

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

using namespace std;

int sleep_10s()
{
    this_thread::sleep_for(chrono::seconds(10));
    cout << "Sleeping Done\n";
    return 3;
}

int main()
{
    auto result=async(launch::async, sleep_10s);
    auto status=result.wait_for(chrono::seconds(1));
    if (status==future_status::ready)
        cout << "Success" << result.get() << "\n";
    else
        cout << "Timeout\n";
}
#包括
#包括
#包括
#包括
使用名称空间std;
int sleep_10s()
{
这个线程:睡眠(时间:秒(10));

coutC++11标准没有提供直接的方法来取消以
std::async
启动的任务。您必须实现自己的取消机制,例如将原子标志变量传递给异步任务,该任务将定期检查


但是,您的代码不应该崩溃。当到达
main
的末尾时,保存在
result
中的
std::future
对象将被销毁,它将等待任务完成,然后丢弃结果,清理所有使用的资源。

这里是一个简单的示例,使用原子bool在原子bool可能被包装在一个取消类中(取决于味道)

#包括
#包括
#包括
使用名称空间std;
int long_running_任务(int target,const std::atomic_bool&取消)
{
//为目标*100ms模拟长时间运行的任务,
//任务应经常检查是否已取消!
while(目标--&&!已取消)
这个线程::sleep_for(chrono::毫秒(100));
//将结果返回到将来或引发错误
//如果取消
退货取消?1:0;
}
int main()
{
std::原子布尔取消令牌;
自动任务10秒=异步(启动::异步,
长时间运行的任务,
100, 
std::ref(取消令牌);
自动任务\u 500\u毫秒=异步(启动::异步,
长时间运行的任务,
5.
std::ref(取消令牌);
//做其他事情(应该允许短任务
//在长任务将被取消时完成)
这个线程::sleep_for(chrono::seconds(1));
//取消
取消令牌=真;
//等待取消/结果

cout我知道这是一个老问题,但在搜索时它仍然是“detach std::future”的首选结果。我提出了一个简单的基于模板的方法来处理这个问题:

template <typename RESULT_TYPE, typename FUNCTION_TYPE>
std::future<RESULT_TYPE> startDetachedFuture(FUNCTION_TYPE func) {
    std::promise<RESULT_TYPE> pro;
    std::future<RESULT_TYPE> fut = pro.get_future();

    std::thread([func](std::promise<RESULT_TYPE> p){p.set_value(func());},
                std::move(pro)).detach();

    return fut;
}
如果myFuture超出范围并被破坏,线程将继续执行它正在执行的任何操作,而不会导致问题,因为它拥有std::promise及其共享状态。适用于您有时只希望忽略计算结果而继续(我的用例)的情况

对于OP的问题:如果你到达main的末尾,它将在不等待未来完成的情况下退出

此宏是不必要的,但如果您要频繁调用此宏,则可以节省键入时间

// convenience macro to save boilerplate template code
#define START_DETACHED_FUTURE(func) \
    startDetachedFuture<decltype(func()), decltype(func)>(func)

// works like so:
auto myFuture = START_DETACHED_FUTURE(myFunc);
//保存样板模板代码的方便宏
#定义开始和未来(func)\
startDetachedFuture(func)
//工作原理如下:
自动myFuture=开始\分离\未来(myFunc);

您的代码不应该崩溃。这听起来像是一个问题,您的C++库实现了<代码>启动::AsYNC/<代码>。@ NICOBOLAS如果没有调用<代码> STD::NoW::GET(),应该发生什么?
然后到达main的末尾?标准是否规定了这一点?我之所以这样问是因为当我看到程序在退出main时崩溃,而没有加入
std::thread
(GCC 4.6或4.7)。如果销毁时未加入或分离
std::thread
,则实现将调用
std::terminate
,以中止程序。使用
std::async
可避免此问题,它将等待任务完成。我假设您使用的是GCC,在这种情况下,segfault就是此错误:-我正在检查本周的修复程序d、 这个问题:处理“分离”OP问题的一部分。标志真的必须是原子的吗?比如说,如果你有一个递归搜索函数,并且希望在其中一个线程找到结果时取消所有线程。即使只是在从标志中读取
false
,但在处理该信息之前,在线程a中,成功的线程B将
true
写入t标记时,不会造成真正的伤害,因为在下一个递归深度上,线程A仍将取消自身。只要写入是单向的(仅从
false
true
)不应该存在正确性问题,即使是同时写入也不应该存在正确性问题。这种推理正确吗?从一个线程写入非原子变量,然后在不同步的情况下从另一个线程读取该变量(例如,在写入和读取时锁定相同的互斥锁)是未定义的行为。“它的工作原理与我尝试时的预期相同”是UB的一个可能结果,但您可能会得到不同的结果(例如崩溃)在其他情况下。@rhalbersma:该标准特别允许对内存访问进行重新排序。例如,接收信息的线程可以在检查标志之前加载结果,或者发布线程可以在发布结果之前更新标志。原子变量将不允许发生这种重新排序。这是不够的仅在写操作期间使用互斥锁---读操作和写操作必须使用相同的互斥锁。如果它只是一个简单的布尔变量(如此处所示),而且您正在使用C++11库,只要使用
std::atomic
,编译器就会为您处理好所有事情。@rhalbersma Yep,这是可能的。请参阅。如果您的实现执行了诸如将true设置为0xFFFF和false设置为0x0000之类的操作,您就可以完成0x00FF的写入和读取,这既不是真的,也不是假的。很好。我正在寻找的情况是超出此范围的一步:我希望行为类似于
std::shared_future
,但删除一组
std::shared_future
s中的最后一个会导致它正在等待的线程被取消。也就是说,我希望在一个线程中启动一个昂贵的计算,并使一个或多个对象能够获得当它可用时它的结果,但是如果所有这些
int main(int argc, char ** argv) {
    auto returner = []{fprintf(stderr, "I LIVE!\n"); sleep(10); return 123;};

    std::future<int> myFuture = startDetachedFuture<int, decltype(returner)>(returner);
    sleep(1);
}
$ ./a.out 
I LIVE!
$
// convenience macro to save boilerplate template code
#define START_DETACHED_FUTURE(func) \
    startDetachedFuture<decltype(func()), decltype(func)>(func)

// works like so:
auto myFuture = START_DETACHED_FUTURE(myFunc);