0

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

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

4

2 回答 2

1

NoSenseEtAl 提供了以下链接:

http://fpcomplete.com/functional-patterns-in-c/

Bartosz 提供了一些非常通用的可组合异步 API 的示例代码。我无耻地将其剥离为仅我需要(并且可以理解)的内容。只是“异步或组合器”:

#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();
}
于 2012-10-04T20:35:10.703 回答
0

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

于 2012-10-04T17:38:25.593 回答