下面的代码基于Herb Sutter关于.then()类型延续的实现的想法.
template<typename Fut, typename Work>
auto then(Fut f, Work w)->std::future<decltype(w(f.get()))>
{ return std::async([=] { w(f.get()); }); }
Run Code Online (Sandbox Code Playgroud)
这可以像auto next = then(f, [](int r) { go_and_use(r); });或类似地使用.
这是一个很好的想法,但它现在不起作用(期货只是移动而不是可复制的).我喜欢这个想法,因为它可能出现在即将推出的c ++版本中,据我所知(尽管是.then()甚至是等待.)
在让期货共享或类似之前,我想知道堆栈溢出社区会特别考虑改进和建议(甚至是共享期货)对这种实现的看法?
在此先感谢您的任何建议.
(我知道这是一个修复,直到基于标准的机制存在,因为它将花费一个线程(也许))).
我一直在考虑std::async以及如何在将来的编译器实现中使用它.但是,现在我有点陷入一种感觉像是设计缺陷的东西.
这std::async几乎与实现有关,可能有两种变体launch::async,一种是将任务启动到新线程,另一种是使用线程池/任务调度程序.
但是,根据用于实现的这些变体中的哪一个std::async,使用情况会有很大差异.
对于基于"线程池"的变体,您可以启动许多小任务而不必担心开销,但是,如果其中一个任务在某些时候阻塞了怎么办?
另一方面,"启动新线程"变体不会遇到阻塞任务的问题,另一方面,启动和执行任务的开销将非常高.
线程池: +低开销,永不阻塞
启动新线程: +精细的块,高开销
所以基本上取决于实现,我们使用的方式std::async会非常谨慎.如果我们有一个适用于一个编译器的程序,它可能在另一个编译器上工作可怕.
这是设计的吗?或者我错过了什么?你会像我一样考虑这个问题吗?
在当前的规范中,我遗漏了类似的东西std::oversubscribe(bool),以便实现依赖的使用std::async.
编辑:据我所知,C++ 11标准文档没有提供有关发送的任务是否std::async阻止的任何提示.
考虑以下代码
void printPromised(std::future<int> f)
{
std::cout << f.get() << std::endl;
}
int main()
{
printPromised(std::async(std::launch::async, [](){ return 8; })); // This works
auto f = std::async(std::launch::async, [](){ return 8; });
printPromised(f); // This won't work
}
Run Code Online (Sandbox Code Playgroud)
它说"这是一个删除的功能".这是为什么?此外,我需要传递(共享)std::async生成的相同承诺结果; 给多个用户.这意味着当有人调用"getter"时,我需要传递相同的结果(std::async如果已经生成了,我不需要重新生成结果)并且我还需要具有的阻塞机制std::future::get.
从Herb Sutter的演示中运行此代码.这在gcc 4.6.3下的linux下工作正常.我认为mingw不支持future.h,但错误很难理解!
#include <iostream>
#include <vector>
#include <string>
#include <future>
#include <algorithm>
using namespace std;
string flip( string s ) {
reverse( begin(s), end(s) );
return s;
}
int main() {
vector<future<string>> v;
v.push_back( async([]{ return flip(" ,olleH"); }) );
v.push_back( async([]{ return flip(".gnaL"); }) );
v.push_back( async([]{ return flip("\n!TXEN"); }) );
for( auto& e: v ) {
cout << e.get();
}
}
Run Code Online (Sandbox Code Playgroud)
这是错误:
$ x86_64-w64-mingw32-g++.exe -std=c++0x -pthread swap.cpp
swap.cpp: In function 'int main()':
swap.cpp:17:51: error: invalid …Run Code Online (Sandbox Code Playgroud) 我有一个函数模板,我想完美转发到我在另一个线程上运行的lambda.这是一个可以直接编译的最小测试用例:
#include <thread>
#include <future>
#include <utility>
#include <iostream>
#include <vector>
/**
* Function template that does perfect forwarding to a lambda inside an
* async call (or at least tries to). I want both instantiations of the
* function to work (one for lvalue references T&, and rvalue reference T&&).
* However, I cannot get the code to compile when calling it with an lvalue.
* See main() below.
*/
template <typename T>
std::string accessValueAsync(T&& obj)
{
std::future<std::string> fut …Run Code Online (Sandbox Code Playgroud) 我有一个返回std::future. 我已经在实现中添加了一个缓存,如果不需要重新计算,我想选择立即返回一个值。
我怎样才能创造一个已经解决的未来?
// Class declarations shortened to minimal example to communicate intent
class MyClass {
Cache m_cache;
std::future<int> foo(int arg);
}
class Cache {
std::optional<int> get(int arg);
}
std::future<int> MyClass::foo(int arg) {
if (auto res = m_cache.get(arg)) {
// *res is my result
return std::future(*res); // ????? Doesn't work
}
// If the cache misses, we need to calculate it
// Fire up the ol' thread pool and get to work
return std::launch(std::launch::async /* ommited for brevity …Run Code Online (Sandbox Code Playgroud) 可能重复:
考虑以下C++示例
class A
{
public:
int foo(int a, int b);
int foo(int a, double b);
};
int main()
{
A a;
auto f = std::async(std::launch::async, &A::foo, &a, 2, 3.5);
}
Run Code Online (Sandbox Code Playgroud)
这给出了'std :: async':不能推断模板参数,因为函数参数是不明确的.我该如何解决这种歧义?
可能重复:
有没有办法在C++ 11中取消/分离未来?
有一个成员函数使用std::future和异步运行std::async.在某些情况下,我需要取消它.(该函数连续加载对象附近,有时加载时对象超出范围.)我已经阅读了这个问题的答案,解决了同样的问题,但我不能让它工作.
这是简化的代码,其结构与我的实际程序相同.在异步运行时调用Start(),Kill()因为访问冲突而导致崩溃input.
在我看来,代码应该如下工作.当Kill()被调用时,行驶标志被禁用.下一个命令get()应该等待线程结束,它会很快检查运行标志.线程取消后,input指针将被删除.
#include <vector>
#include <future>
using namespace std;
class Class
{
future<void> task;
bool running;
int *input;
vector<int> output;
void Function()
{
for(int i = 0; i < *input; ++i)
{
if(!running) return;
output.push_back(i);
}
}
void Start()
{
input = new int(42534);
running = true;
task = async(launch::async, &Class::Function, this);
}
void Kill()
{
running = …Run Code Online (Sandbox Code Playgroud) 是否可以使用std :: async调用使用std :: bind创建的函数对象.以下代码无法编译:
#include <iostream>
#include <future>
#include <functional>
using namespace std;
class Adder {
public:
int add(int x, int y) {
return x + y;
}
};
int main(int argc, const char * argv[])
{
Adder a;
function<int(int, int)> sumFunc = bind(&Adder::add, &a, 1, 2);
auto future = async(launch::async, sumFunc); // ERROR HERE
cout << future.get();
return 0;
}
Run Code Online (Sandbox Code Playgroud)
错误是:
没有用于调用'async'的匹配函数:忽略候选模板:替换失败[使用Fp = std :: _1 :: function&,Args = <>]:'std :: _1 :: __ invoke_of中没有名为'type'的类型 …
我知道了future返回的原因std::async有一些特殊的共享状态,通过它wait on returned future发生在未来的析构函数中。但是当我们使用 时std::pakaged_task,它的未来不会表现出相同的行为。为了完成任务打包,你必须显式调用get()上future的对象packaged_task。
现在我的问题是:
std::async与std::packaged_task)的内部实现可能是什么?futurereturn from std::packaged_task?或者,换句话说,相同的行为是如何停止的std::packaged_task future?要查看上下文,请查看以下代码:
它不会等待完成countdown任务。但是,如果我取消评论// int value = ret.get();,它就会结束countdown并且很明显,因为我们实际上是在阻止返回的未来。
// packaged_task example
#include <iostream> // std::cout
#include <future> // std::packaged_task, std::future
#include <chrono> // std::chrono::seconds
#include <thread> // std::thread, std::this_thread::sleep_for
// count down taking a second for each value:
int countdown (int from, …Run Code Online (Sandbox Code Playgroud) c++ ×10
stdasync ×10
c++11 ×8
std-future ×2
c++14 ×1
concurrency ×1
crash ×1
lambda ×1
mingw ×1
overloading ×1
std-function ×1