【问题标题】:Pass argument to std::bind at run time to a dispatch Queue在运行时将参数传递给 std::bind 到调度队列
【发布时间】:2020-08-23 07:04:38
【问题描述】:

我无法将参数传递给以函数指针作为参数的调度队列。我已经实现了一个调度队列,比如this tutorial

typedef std::function<std::string( const std::array<float, kMaxSamples> &)> fp_t;


class DispatchQueue {
public:
    DispatchQueue(std::string name, size_t thread_cnt = 1);
    ~DispatchQueue();
    //move
    void dispatch(fp_t && item); //Take the typedef defined above

private:

    std::string _name;
    std::queue<fp_t> _q;
    std::vector<std::thread> _threads;
    void dispatch_thread_handler(void);
    std::mutex _lock;
    std::condition_variable _cv;
    bool _quit;
};

我的 std::function 将 std::array 作为参数。

然后,稍后在我的代码中,我将这个特定作业添加到队列中以处理此参数。

queue-&gt;dispatch(std::bind(&amp;AudioRecordEngine::run, mRecordingCallbackImp.getAudioData()));

dispatch函数定义为:

void DispatchQueue::dispatch(fp_t &&item)
{
   std::unique_lock<std::mutex> lock(_lock);

    _q.push(item);

    // Manual unlocking is done before notifying, to avoid waking up
    // the waiting thread only to block again (see notify_one for details)
    lock.unlock();
    _cv.notify_one();
}`

也许这个用例太复杂了,我可能不知道如何做得更好。

非常感谢您的建议和帮助。我被困了很长一段时间。

非常感谢

编辑: 我面临的问题是在编译时:

从 '__bind<:__ndk1::__bind std::__ndk1::char_traits std::__ndk1::allocator> (AudioRecordEngine::*) 没有可行的转换(const std::__ndk1::array &), std::__ndk1::array > >' to 'fp_t' (aka 'function (常量数组 &)>')

似乎我的 std::function 不支持我传递的参数。这个问题看起来我没有正确使用 std::bind。

基本上我想将带有给定参数的函数指针传递给我的调度函数。

编辑 2:

AudioRecordEngine::run 定义为:

   std::string AudioRecordEngine::run(const std::array<float,    __NUM_SAMPLES__> & audioData) {
    std::thread::id this_id = std::this_thread::get_id();
    LOGD("In the thread ID %zu  \n", this_id);
    //double freq = FFTNativeWrapper::fftEntryPoint(audioData);
    //LOGD("In the Thread, FFT analysis == %zu  \n", freq);
    return "from thread";
}


std::array<float, kMaxSamples> RecordingCallbackImp::getAudioData() {
return mData;

}

【问题讨论】:

  • 我编辑了我的帖子,并在编译时给出了错误。如果还不清楚,请告诉我。谢谢你的时间。我不确定参数是否会正确传递给调度函数。这对我来说是一个相当复杂的问题。
  • 如果您包含AudioRecordEngine::run 和getAudioData() 的声明也会有所帮助。
  • std::function 需要一个参数。您的 std::bind 不包含占位符,因此它为您提供了一个没有参数的函数(而是一个函数对象)。此外,要调用成员函数 (run),您必须提供 AudioRecordEngine 类型的对象作为第一个参数。
  • 你如何调用来自_q的功能对象?
  • getAudioData 或 getRecordData?

标签: c++ parameter-passing std-function


【解决方案1】:
  1. 在DispatchQueue的实现中,fp_t类型的函数对象被调用为fn(),所以fp_t应该是std::function&lt;std::string()&gt;或std::function&lt;void()&gt;。应该没有const std::array&amp; 参数。

  2. std::bind 应该给你一些不带参数的东西。你的std::bind 几乎是正确的。当你想调用一个非静态成员函数时,你需要一个对象。该对象,以指针或引用的形式,应该是std::bind 的第二个参数:

    AudioRecordEngine engine;
    
    queue->dispatch(std::bind(
        &AudioRecordEngine::run,
        std::ref(engine),
        mRecordingCallbackImp.getAudioData()
    ));
    

    注意engine 的生命周期。

  3. 或者,您可以使用 lambda 函数代替 std::bind:

    AudioRecordEngine engine;
    
    queue->dispatch([&] { 
        engine.run(mRecordingCallbackImp.getAudioData());
    });
    

    这和之前的方法在调用getAudioData()的时候不同:2中,getAudioData()的执行结果存储在std::bind返回的函数对象中,3中,getAudioData()只是被调用在调用 run 之前。

Minimal example

【讨论】:

  • 感谢您的帮助。问题是调度函数采用的函数对象不是 fp_t 类型。从 '(lambda at... 到 'fp_t' (aka 'function, allocator > ()>') 没有可行的转换,这是可以理解的。问题是,我在通过调度队列,我不想丢失传递的参数。也许我的设计有问题。
  • @RemyS,对不起,我不太明白问题所在。队列执行可以使用空参数列表调用的功能对象,即fn()。您传递给run 的内容要么存储在功能对象中(std::bind 的解决方案),要么在调用功能对象时计算(使用 lambda 的解决方案)。我不确定这是一个好还是坏的设计,但至少它应该编译。
  • @RemyS,尝试手动调用它,并确保调用 lambda 时 this 对象仍然存在。
  • 感谢解释,代码已经编译,我的参数可以被调度队列处理。之所以没有调用我的运行函数,是因为我已将功能对象的调用注释到调度队列中。这是我的错。非常感谢@Evg,我选择了 lambda,代码比 std::bind 短。但它们都运作良好。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-05-05
  • 2014-08-23
相关资源
最近更新 更多