两个完全相同的(网络)呼叫。如何等待最快,丢弃最慢?

时间:2012-10-04 15:56:47

标签: c++ c++11 stdthread

在c ++ 11中,如何实现一个执行两个相同类型的昂贵(网络)调用的程序,然后只等待更快的结果,而不是等待并丢弃较慢的结果。 std :: thread无法中断,也不会返回方便的std :: future。并且返回未来的std :: async既不能被中断也不能被分离。

两个主要问题是: - 更快的结果到达时的通知。 - 终止(并清理)较慢的线程。

2 个答案:

答案 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)

您必须使用操作系统提供的工具来发出“真正的”异步操作,以便在完成时发送某种形式的通知。这些操作通常可以在完成之前终止;如果他们不能找到其他机制,或者只是让他们完成并忽略结果。