在c ++ 11中,如何实现一个执行两个相同类型的昂贵(网络)调用的程序,然后只等待更快的结果,而不是等待并丢弃较慢的结果。 std :: thread无法中断,也不会返回方便的std :: future。并且返回未来的std :: async既不能被中断也不能被分离。
两个主要问题是: - 更快的结果到达时的通知。 - 终止(并清理)较慢的线程。
答案 0 :(得分:1)
NoSenseEtAl提供了以下链接:
http://fpcomplete.com/functional-patterns-in-c/
Bartosz提供了一些非常通用的可组合异步API的示例代码。我无耻地将它剥离到我需要的东西(并且可以理解)。只是“Async Or-Combinator”:
#include <functional>
#include <iostream>
#include <string>
#include <memory>
#include <algorithm>
#include <ctype.h>
#include <thread>
#include <mutex>
#include <chrono>
#include <random>
using namespace std;
//--------
// Helpers
//--------
void tick(int n)
{
for(int i = 0; i < n; ++i)
{
cout << i << endl;
this_thread::sleep_for(chrono::seconds(1));
}
}
//-------
// Async
//-------
template<class A>
struct Async {
virtual ~Async() {}
virtual void andThen(function<void(A)>) = 0;
};
//-------
// Monoid
//-------
template<class A>
struct Mplus : Async<A>
{
Mplus(unique_ptr<Async<A>> asnc1, unique_ptr<Async<A>> asnc2)
: _asnc1(move(asnc1)), _asnc2(move(asnc2)), _done(false)
{}
~Mplus() {}
void andThen(function<void(A)> k)
{
_asnc1->andThen([this, k](A a)
{
lock_guard<mutex> l(_mtx);
if (!_done)
{
_done = true;
k(a);
}
});
_asnc2->andThen([this, k](A a)
{
lock_guard<mutex> l(_mtx);
if (!_done)
{
_done = true;
k(a);
}
});
}
unique_ptr<Async<A>> _asnc1;
unique_ptr<Async<A>> _asnc2;
bool _done;
mutex _mtx;
};
template<class A>
unique_ptr<Async<A>> mplus(unique_ptr<Async<A>> asnc1, unique_ptr<Async<A>> asnc2)
{
return unique_ptr<Async<A>>(new Mplus<A>(move(asnc1), move(asnc2)));
}
//----------------
// Fake async APIs
//----------------
void getStringAsync(string s, function<void(string)> handler)
{
thread th([s, handler]()
{
cout << "Started async\n";
size_t sleep = rand () % 10;
this_thread::sleep_for(chrono::seconds(sleep));
handler("Done async: " + s);
});
th.detach();
}
struct AsyncString : Async<string>
{
AsyncString(string s) : _s(s) {}
void andThen(function<void(string)> k)
{
getStringAsync(_s, k);
}
string _s;
};
unique_ptr<Async<string>> asyncString(string s)
{
return unique_ptr<Async<string>>(new AsyncString(s));
}
void testOr()
{
// Test or combinator / mplus
auto or = mplus<string>(asyncString(" Result One "), asyncString(" Result Two "));
or->andThen([](string s)
{
cout << "Or returned : " << s << endl;
});
tick(10);
}
void main()
{
srand ( time(NULL) );
testOr();
}
答案 1 :(得分:0)
您必须使用操作系统提供的工具来发出“真正的”异步操作,以便在完成时发送某种形式的通知。这些操作通常可以在完成之前终止;如果他们不能找到其他机制,或者只是让他们完成并忽略结果。