I have trouble to pass an argument to my dispatch queue that takes a function pointer as a parameter. I have implemented a Dispatch Queue like 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;
};
My std::function takes an std::array as a parameter.
Then, later in my code I add in the queue this particular job to process this argument.
queue->dispatch(std::bind(&AudioRecordEngine::run, mRecordingCallbackImp.getAudioData()));
The dispatch function is defined as:
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();
}`
Maybe it is too complicated for this use case, I probably don't know how to do better.
I would greatly appreciate suggestion and help. I am stuck for quite a while.
Thanks a lot
EDIT: The problem I am facing is at compilation time:
no viable conversion from '__bind<std::__ndk1::__bind<std::__ndk1::basic_string<char, std::__ndk1::char_traits, std::__ndk1::allocator > (AudioRecordEngine::*)(const std::__ndk1::array<float, 44100> &), std::__ndk1::array<float, 44100> > >' to 'fp_t' (aka 'function<basic_string<char, char_traits, allocator > (const array<float, kMaxSamples> &)>')
It seems that my std::function do not support the argument I am passing. The problem look like I do not use the std::bind properly.
Basically I would like to pass to my dispatch function the function pointer with the given argument.
EDIT 2:
The AudioRecordEngine::run is defined as:
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;
}
Inside the implementation of DispatchQueue
, functional objects of type fp_t
are invoked as fn()
, so fp_t
should be std::function<std::string()>
or std::function<void()>
. There should be no const std::array&
parameter.
std::bind
should give you something that takes no parameters. Your std::bind
is almost correct. When you want to invoke a non-static member function, you need an object. That object, in the form of a pointer or a reference, should be the second argument of std::bind
:
AudioRecordEngine engine;
queue->dispatch(std::bind(
&AudioRecordEngine::run,
std::ref(engine),
mRecordingCallbackImp.getAudioData()
));
Be careful about engine
life time.
Alternatively, you can use a lambda function instead of std::bind
:
AudioRecordEngine engine;
queue->dispatch([&] {
engine.run(mRecordingCallbackImp.getAudioData());
});
This and the previous approaches differ by the moment when getAudioData()
is called: in 2, the result of getAudioData()
execution is stored inside the functional object returned by std::bind
, in 3, getAudioData()
is invoked just before run
is called.