Threading a bool function passing string argument - c++

I am new working with threads.. but I got the concept and have been playing with it in the last days.
But now I am trying to create a thread calling a bool function and passing a string as argument. The code is basically:
bool className::analyseData(const std::string& filename) {
...
return true;
}
bool className::equalise(...) {
...
const std::string filename0 = filenameBase + "_chip" + ss.str() + "_0";
std::thread analyse_dat0(analyseData, &filename0);
...
return true;
}
and then I call equalise from other place.
But when I try to compile it I get the following error:
SpidrEqualisation_multi_threading.cpp:140:50: error:
no matching function for call to ‘std::thread::thread(<unresolved overloaded function type>, const string&)
std::thread analyse_dat0(analyseData, filename0);`
Any idea about how I can fix that?
Many thanks for the help.

You don't want to pass a pointer to that thread function:
std::thread analyse_dat0(analyseData, filename0); // omit the &
// address of operator

Instead of using std::thread for this purpose why not use std::async and get the result as std::future ? That's much simpler, IMO.
Class c;
auto ft = std::async([&] { return c.analyseData("file.txt"); });
bool result = ft.get();

Remove the & from td::thread analyse_dat0(analyseData, &filename0); as you want a reference not a pointer in analyseData.
Also you need to provide an object as analyseData isn't static.

Related

Pass argument to std::bind at run time to a dispatch Queue

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.
Minimal example

Compiler error when trying using std::thread

I ran into a compiler error when I tried to execute a function using std::thread. The error says : "error C2672: 'std::invoke': no matching overloaded function found".
Here is a code snippet:
void GetMinMax_X(const std::vector<Vertex>& iAllVertices, double & oMin_X,
double & oMax_X)
{
auto MinMax_X = std::minmax_element(iAllVertices.begin(),
iAllVertices.end(), [](const Vertex& i, const Vertex& j)
{
return i.GetX() < j.GetX();
});
oMin_X = MinMax_X.first->GetX();
oMax_X = MinMax_X.second->GetX();
}
int main()
{
std::vector<Vertex>;
// Some functions to fill the Vertex vector......
double Min_X = 0;
double Max_X = 0;
std::thread first (GetMinMax_X, AllVertices, Min_X, Max_X);
first.join();
return 0;
}
Thanks!
The error comes up because std::thread uses std::invoke behind the scenes to invoke GetMinMax_X, but with the arguments copied/moved. In particular, you cannot use
void GetMinMax_X(const std::vector<int>& iAllVertices, double & oMin_X, double & oMax_X)
because you would be forming references to the copies, which is not what you want.
You could still use
void GetMinMax_X(const std::vector<int>& iAllVertices, const double & oMin_X, const double & oMax_X)
but that would not help you get back the values into the main thread.
The solution is to use std::ref:
std::thread first(GetMinMax_X, AllVertices, std::ref(Min_X), std::ref(Max_X));
https://godbolt.org/z/ClK3Cb
See also what cppreference has to say about std::thread (where this "limitation" and the workaround are described):
https://en.cppreference.com/w/cpp/thread/thread/thread
The arguments to the thread function are moved or copied by value. If a reference argument needs to be passed to the thread function, it has to be wrapped (e.g. with std::ref or std::cref).
Any return value from the function is ignored. If the function throws an exception, std::terminate is called. In order to pass return values or exceptions back to the calling thread, std::promise or std::async may be used.

CPP std::thread attempt to use a deleted function

First of all, I want to say that i already made researches on the subject, but nothing relevant...
(Error creating std::thread on Mac OS X with clang: "attempt to use a deleted function")
(Xcode 7: C++ threads ERROR: Attempting to use a deleted function)
(xcode - "attempt to use a deleted function" - what does that mean?)
And here's my issue...:
clang error:
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/thread:347:5: error: attempt to use a deleted function
__invoke(_VSTD::move(_VSTD::get<0>(__t)), _VSTD::move(_VSTD::get<_Indices>(__t))...);
And that's my code:
bool GenAI::loadAIs()
{
bool ret = true;
if (_nbThread > 1)
{
std::vector<std::thread> threads;
for (unsigned int i = 0; i < _nbThread; ++i)
threads.push_back(std::thread(static_cast<void (GenAI::*)(bool &, unsigned int)>(&GenAI::loadAIs), this, ret, i));
for (unsigned int i = 0; i < _nbThread; ++i)
threads[i].join();
}
else
loadAIs(ret, 0);
return ret;
}
// And the prototype of the function that i try to call
void GenAI::loadAIs(bool & ret, unsigned int iThread);
If some one could help me that'd be really helpful ! :)
Regards ;)
To pass reference to thread, you have to use std::reference_wrapper, that you can obtain with std::ref. So your code becomes:
threads.emplace_back(static_cast<void (GenAI::*)(bool &, unsigned int)>(&GenAI::loadAIs),
this,
std::ref(ret),
i));
Note:
bool ret should probably be std::atomic<bool> ret, or should should have one bool by thread. Else you may have concurrent access on ret.
The deleted function that it is complaining about is a deleted copy constructor for const thread.
For the deleted function problem, you can use:
threads.emplace_back(
Instead of:
threads.push_back(
What the commenter also referred to is that the function is creating more than one thread and passing to them a reference to the same boolean return variable.
It will crash if you don't use atomic_bool and even if you do, they will all report back to the same memory location, making the function miss the notification if one of them returns false.

c++ remove custom object from vector : std::remove_if': no matching overloaded function found

In my project there is a vector
std::vector<std::shared_ptr<MovingEntity>>gameObjects;
Which I want to delete elements from if they meet the criteria.
Method to delete elements:
void GameWorld::catchBees()
{
auto q = std::remove_if(bees.begin(), bees.end(), beeToClose);
bees.erase(q);
}
Method beeToClose:
bool GameWorld::beeToClose( const MovingEntity & bee)
{
std::shared_ptr<Beekeeper> keeper = std::static_pointer_cast<Beekeeper>(m_beekeeper);
if (bee.getConstPosition().distanceTo(m_beekeeper->getPosition()) > keeper->getCatchDistance())
{
return true;
}
return false;
}
When I try to compile the code I get some errors which I tried to understand:
'GameWorld::beeToClose': non-standard syntax; use '&' to create a
pointer
Not sure why this message is given
'std::remove_if': no matching overloaded function found
I did not declare beeToClose right?
'q': cannot be used before it is initialized SDLFramework
q is not initialized because:
std::remove_if(bees.begin(), bees.end(), beeToClose);
does not run correct?
How can I remove a std::shared_ptr correctly from a vector correctly when meeting some criteria?
The syntax for forming a pointer to member function is &ClassName::FunctionName. So you need &GameWorld::beeToClose for a pointer to the beeToClose member function. In your case, you should use a lambda from which you call that function
auto q = std::remove_if(bees.begin(), bees.end(),
[&](shared_ptr<MovingEntity> const& bee){ return beeToClose(bee); });
Also, you're using the wrong vector::erase overload, you want the one that erases a range of elements, not the one that erases a single element.
bees.erase(q, bees.end());
The vector contains std::shared_ptr<MovingEntity> elements, so beeToClose() needs to accept a const std::shared_ptr<MovingEntity> & parameter as input, not a const MovingEntity & parameter. Also, beeToClose() appears to be a non-static class method that accesses a non-static class member (m_beekeeper), so you can't just pass beeToClose() directly to std::remove_if() as it does not have access to the calling object's this pointer, but you can wrap it in a lambda to capture the this pointer.
Try this:
void GameWorld::catchBees()
{
auto q = std::remove_if(bees.begin(), bees.end(),
[this](const const std::shared_ptr<MovingEntity> &bee) {
return this->beeToClose(bee);
}
);
bees.erase(q, bees.end());
}
bool GameWorld::beeToClose(const std::shared_ptr<MovingEntity> &bee)
{
std::shared_ptr<Beekeeper> keeper = std::static_pointer_cast<Beekeeper>(m_beekeeper);
return (bee->getConstPosition().distanceTo(m_beekeeper->getPosition()) > keeper->getCatchDistance());
}
You might also consider moving the distance calculation into Beekeeper instead:
bool GameWorld::beeToClose(const std::shared_ptr<MovingEntity> &bee)
{
std::shared_ptr<Beekeeper> keeper = std::static_pointer_cast<Beekeeper>(m_beekeeper);
return !keeper->isInCatchDistance(bee);
}
bool Beekeeper::isInCatchDistance(const std::shared_ptr<MovingEntity> &bee)
{
return (bee->getConstPosition().distanceTo(getPosition()) <= getCatchDistance());
}

Passing a bool as a param. C++

what I am trying to do is an example below.
let's first define a bool.
bool cat = {false};
lets make a fake bool here.
bool setcat(bool booltoset)
{
booltoset = true;
return booltoset;
}
now lets call it with cat.
printf("cat is %s", cat?"true":"false"); //set cat as false.
my question is; is it possible to actually pass a bool through an argument than set that bool?
You need to pass by reference, i.e.:
void setcat(bool& booltoset)
{
booltoset = true;
}
Any function argument is just a variable with scope identical to the function body. If it's an ordinary automatic variable, then changing it has not effect on the caller. This is sometimes useful: you can actually use the arguments, for example:
template<typename F>
void for_each(noexcept_it i, const noexcept_it end, const F &f) noexcept(noexcept(f))
{
for(; i!=end; ++i) f(i); // use i as iteration variable.
}
though the compiler will optimise such things anyway in most cases.