首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >从生产者线程调用成员函数

从生产者线程调用成员函数
EN

Stack Overflow用户
提问于 2022-09-08 04:44:35
回答 1查看 33关注 0票数 1

使用生产者-使用者模式,我想通过传递函数对象的名称(类似于A )以及这些函数在类似队列的缓冲区queue_in中获取的参数列表来提交对struct func_2()的成员函数的调用。然后,我想收集这些结果(这里是所有可能的返回类型的std::variant (doubleint)),在另一个缓冲区queue_out中进行后续处理。

目前,我只能通过让q_in持有std::string并手动枚举所有可能性来破解自己的方式。当然,我也没有将任何可能的参数传递给func_1()func_2()

代码语言:javascript
复制
#include <iostream>
#include "blockingconcurrentqueue.h" // https://github.com/cameron314/concurrentqueue
#include <variant>
代码语言:javascript
复制
using Result = std::variant<double, int>;
using queue_in = moodycamel::BlockingConcurrentQueue<std::string>;
using queue_out = moodycamel::BlockingConcurrentQueue<Result>;
代码语言:javascript
复制
struct A {

    explicit A(queue_in &q_in, queue_out &q_out) {
        std::thread t([&]() {
            for (;;) {
                std::string s;
                if (q_in.wait_dequeue_timed(s, -1)) {
                    if (s == "1")
                        q_out.enqueue(this->func_1());
                    else if (s == "2")
                        q_out.enqueue(this->func_2());
                }
                std::this_thread::sleep_for(std::chrono::seconds(1));
            }
        });
        t.join();
    }

    double func_1() const { // func_1 might have arguments!
        std::cout << "func_1() called.\n";
        return 13.0f;
    }

    int func_2() const { // func_2 might have arguments!
        std::cout << "func_2() called.\n";
        return 1;
    }
};
代码语言:javascript
复制
void producer(queue_in &q_in, const size_t N) {
    for (size_t i = 0; i != N; ++i) {
        q_in.enqueue("1" /*..., arguments for func_1*/); // prefer to call the function-object instead
        q_in.enqueue("2" /*..., arguments for func_2*/);
    }
}

void result_consumer(queue_out &q_out) {
    for (;;) {
        Result r;
        if (q_out.wait_dequeue_timed(r, -1)) {
            std::visit([](auto &&arg) {
                std::cout << "The result is: " <<  arg << std::endl;
            }, r);
        }
        std::this_thread::sleep_for(std::chrono::seconds(0));
    }
}

int main() {
    const size_t N = 2;
    queue_in q_in;
    queue_out q_out;

    std::thread producer_thread(producer, std::ref(q_in), N);
    std::thread result_consumer_thread(result_consumer, std::ref(q_out));
    A a(q_in, q_out);
    producer_thread.join();
    result_consumer_thread.join();
}

我如何通过函数对象来代替它呢?第二,如何为A的成员函数调用任何可能的参数。第三,我是否可以避免使用类似于std::variant的结果类型?

EN

回答 1

Stack Overflow用户

发布于 2022-09-08 09:51:17

从@n.1.8e9-我的股份在哪里获得灵感。这里的注释是我如何使用std::functionstd::bind实现上述工作的

代码语言:javascript
复制
using Result = std::variant<double, int>;
using FO = std::function<Result(void)>;
using queue_in = moodycamel::BlockingConcurrentQueue<FO>;
using queue_out = moodycamel::BlockingConcurrentQueue<Result>;
代码语言:javascript
复制
struct A {

    explicit A(queue_in &q_in, queue_out &q_out) {
        std::thread t([&]() {
            for (;;) {
                FO o;
                if (q_in.wait_dequeue_timed(o, -1)) {
                    q_out.enqueue(o());
                }
                std::this_thread::sleep_for(std::chrono::seconds(1));
            }
        });
        t.detach();
    }

    void consumer() {
    }

    double func_1(double x, const size_t &s) const { // note the arguments
        std::cout << "func_1() called.\n";
        return x + s;
    }

    int func_2(int x) const { 
        std::cout << "func_2() called.\n";
        return x;
    }
};
代码语言:javascript
复制
void producer(const A& a, queue_in &q_in, const size_t N) { // note the first argument: the producer() must know about some instance of A
    for (size_t i = 0; i != N; ++i) {
        FO o;
        if (i % 2 == 0)
            o = std::bind(&A::func_1, a, double(i), size_t(10));
        else
            o = std::bind(&A::func_2, a, int(i));
        q_in.enqueue(o);
    }
}

void result_consumer(queue_out &q_out) {
    for (;;) {
        Result r;
        if (q_out.wait_dequeue_timed(r, -1)) {
            std::visit([&](auto &&arg) {
                std::cout << "The result is: " <<  arg << std::endl;
            }, r);
        }
        std::this_thread::sleep_for(std::chrono::seconds(1));
    }
}
代码语言:javascript
复制
int main() {
    const size_t N = 2;
    queue_in q_in;
    queue_out q_out;

    A a(q_in, q_out);
    std::thread producer_thread(producer, std::ref(a), std::ref(q_in), N);
    std::thread result_consumer_thread(result_consumer, std::ref(q_out));
    producer_thread.join();
    result_consumer_thread.join();
}

输出:

代码语言:javascript
复制
func_1() called.
The result is: 10
func_2() called.
The result is: 1
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/73643839

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档