简体   繁体   English

使用std :: future / std :: async

[英]Using std::future/std::async

I get some errors when I try to run the next code: 当我尝试运行下一个代码时,出现一些错误:

// tree.cpp
// compile with: g++ -std=c++11 tree.cpp -o tree

#include <iostream>
#include <future>

using namespace std;

int valtab[127]; // used for integer values of variables

class Tree; // forward declare

class Node {
protected:
    Node() { use = 1; }
    virtual void print(ostream &os) = 0;
    virtual ~Node() { }
    virtual int eval() = 0;
private:
   friend class Tree;
   friend ostream& operator<<(ostream&, const Tree&);
   int use; // reference count
};

class Tree {
public:
    Tree(int n); // constant
    Tree(char id); // variable
    Tree(char op, Tree t); // unary operator
    Tree(char op, Tree left, Tree right); // binary operator
    Tree(const Tree &t) { p = t.p; ++p->use; }
    ~Tree() { if (--p->use == 0) delete p; }
    void operator=(const Tree &t);
    int eval() { return p->eval(); }
private:
    friend class Node;
    friend ostream& operator<<(ostream &os, const Tree &t);
    Node *p; // polymorphic hierarchy
};

void Tree::operator=(const Tree &t)
{
    ++t.p->use;
    if (--p->use == 0) 
        delete p;
    p = t.p;
}

ostream& operator<<(ostream &os, const Tree &t)
{
    t.p->print(os);
    return os;
}

class LeafNode: public Node {
private:
    friend class Tree;
    void print(ostream &os) = 0;
    virtual int eval() = 0;
};

class IntNode: public LeafNode {
public:
    int eval() { return n; }
private:
    friend class Tree;
    int n;
    void print(ostream &os) { os << n ;}
    IntNode(int k): n(k) { }
};

class IdNode: public LeafNode {
public:
    int eval() { return valtab[name]; }
private:
    friend class Tree;
    char name;
    void print(ostream& o) { o << name; }
    IdNode(char id): name(id) { }
};

class UnaryNode: public Node {
public:
    int eval();
private:
    friend class Tree;
    const char op;
    Tree opnd;
    UnaryNode(char a, Tree b): op(a), opnd(b) { }
    void print(ostream& o) { o << "(" << op << opnd << ")"; }
};

int UnaryNode::eval()
{
    switch (op) {
        case '-': return (-opnd.eval());
        case '+': return (+opnd.eval());
        default: cerr << "no operand" << endl;
            return 0;
    }
}

class BinaryNode: public Node {
public:
    int eval();
private:
    friend class Tree;
    const char op;
    Tree left;
    Tree right;
    BinaryNode(char a, Tree b, Tree c): op(a), left(b), right(c) { }
    void print(ostream &os) { os << "(" << left << op << right << ")"; }
};

int BinaryNode::eval()
{
    switch (op) {
        case '-': {
            future<int> left = async(launch::async, left.eval());
            future<int> right = async(launch::async, right.eval());
            //return (left.get() - right.get());
            }
        case '+': return (left.eval() + right.eval());
        case '*': return (left.eval() * right.eval());
        default: cerr << "no operand" << endl;
            return 0;
    }
}

Tree::Tree(int n) { p = new IntNode(n); }
Tree::Tree(char id) { p = new IdNode(id); }
Tree::Tree(char op, Tree t) { p = new UnaryNode(op, t); }
Tree::Tree(char op, Tree left, Tree right) { p = new BinaryNode(op, left, right); }

int main()
{   
    valtab['A'] = 3; valtab['B'] = 4;
    cout << "A = 3, B = 4" << endl;
    Tree t1 = Tree('*', Tree('-', 5), Tree('+', 'A', 4));
    Tree t2 = Tree('+', Tree('-', 'A', 1), Tree('+', t1, 'B'));
    cout << "t1 = " << t1 << ", t2 = " << t2 << endl;
    cout << "t1 = " << t1.eval() << ", t2 = " << t2.eval() << endl;

    return 0;
}

This error I received: 我收到此错误:

error: 'class std::future<int>' has no member named 'eval'

I want to change the program so that expressions are evaluated in a parallel fashion. 我想更改程序,以便以并行方式对表达式求值。 But I'm stuck with the future implementation, I do not quite understand how it works. 但是我对未来的实现感到困惑,我不太了解它是如何工作的。 Well, I understands how it works but I don't understand why I'm receiving these errors. 好吧,我知道它是如何工作的,但是我不明白为什么会收到这些错误。

I hope some one can give me some tips or point me in the right direction. 我希望有人能给我一些提示或为我指明正确的方向。

You're trying to invoke a virtual member function as an async, but not properly providing the object to pin it against. 您试图将虚拟成员函数作为异步调用,但未正确提供对象以使其固定。 Further, your use of same-id local vars, while not directly introducing an error, makes this incredibly hard to read. 此外,您同样-ID本地变量的使用,而不是直接引入一个错误,让这个令人难以置信的难以阅读。

I believe this is what you're shooting for: 我相信这是您要拍摄的内容:

auto eLeft = std::async(std::launch::async, std::bind(&Tree::eval, &this->left));
auto eRight = std::async(std::launch::async, std::bind(&Tree::eval, &this->right));
return (eLeft.get() - eRight.get());

Though, to be completely honest, this seems overkill. 不过,老实说,这似乎有些过分。 I see no sense in spinning up two asyncs just to then wait on both . 我看不出有什么意义纺纱两个异步操作只需再等上两个 Why not spin up one , then use the current thread to perform the other half of of your task: 为什么不启动一个 ,然后使用当前线程执行任务的另一半:

auto eRight = std::async(std::launch::async, std::bind(&Tree::eval, &this->right));
return (left.eval() - eRight.get());

The parameter to std::async is a function (or more precisely, a Callable ). std::async的参数是一个函数(或更准确地说,是Callable )。

In particular, you do not invoke the function yourself (which would yield the return value). 特别是,您不必自己调用该函数(这会产生返回值)。 Invoking is done by std::async . 调用由std::async

So these lines: 所以这些行:

future<int> left = async(launch::async, left.eval());
future<int> right = async(launch::async, right.eval());

Should instead read something like: 相反,应阅读如下内容:

 future<int> left_result = std::async(launch::async, [this]() { return left.eval(); });
 future<int> right_result = std::async(launch::async, [this]() { return right.eval(); });

Note that the function call is now wrapped in a lambda. 请注意,函数调用现在包装在lambda中。 Note also that you also reused the names for left and right in your original code, which is more trouble. 还要注意的是,你还重用了名leftright在你的原代码,这是比较麻烦的。 I renamed them here to make it work. 我在这里将其重命名以使其正常运行。

As usual, since you now have concurrency in your program, you need to care about data races . 像往常一样,由于您的程序现在具有并发性,因此您需要关心数据竞争。 Currently this seems to be fine, as all nodes in the tree are distinct, so the async calls don't share any data with each other. 当前,这似乎很好,因为树中的所有节点都是不同的,因此异步调用不会彼此共享任何数据。 But keep it in mind for any future changes. 但是请牢记任何将来的变化。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM