I have the following situation:
int p;
[p]() {
// really complex and really long code executing outside the main thread
}
The lambda object should be instantiated in several places in my code, p being captured every time. The problem is, that the code of the lambda is rather long and depends on p and I don't want to copy&paste the same code everywhere. I am reluctant to capture by reference, as the lambda is executing in the context of a thread and the referenced object may change. What would be the best thing to do? Could capturing a thread_local variable by reference help in some way?
EDIT:
in the end I went like this:
::std::function<void(int)> f; // captures the lambda
int p;
run_in_thread(::std::bind(f, p));
The reason why I didn't think of this before, was a discussion about the superiority of lambdas over ::std::bind, but apparently they are not for all purposes.
If you want clean code you should generally avoid lambdas with large bodies. So the cleanest solution is probably to move your code into a new function which the lambda in turn calls.
void complexFunction(int p) {
// really complex and really long code executing outside the main thread
}
void run() {
for(int i = 0; i < 10; ++i)
runThread([i]() {complexFunction(i);});
}
Related
I have a class called MatrixAlt and i'm trying to multi thread a function to do some work on that matrix.
My general method worked when I just implemented it in a couple of functions. But when I try to bring it into the class methods, I get an error.
The problematic line (or where it highlights anyway) is 4 lines from the end and the error message is in the comments just above it.
#include <vector>
#include <future>
#include <thread>
class MatrixAlt
{
public:
MatrixAlt();
// initilaise the matrix to constant value for each entry
void function01(size_t maxThreads);
void function02(size_t threadIndex);
};
MatrixAlt::MatrixAlt()
{
}
void MatrixAlt::function02(size_t threadIndex)
{
// do some stuff
return;
}
void MatrixAlt::function01(size_t maxThreads)
{
// To control async threads and their results
std::vector<std::future<bool>> threadsIssued;
// now loop through all the threads and orchestrate the work to be done
for (size_t threadIndex = 0; threadIndex < maxThreads; ++threadIndex)
{
// line 42 gives error:
// 'MatrixAlt::function02': non-standard syntax; use '&' to create a pointer to member
// 'std::async': no matching overloaded function found
threadsIssued.push_back(std::async(function02, threadIndex));
}
return;
}
Your first problem is solved like this
threadsIssued.push_back(std::async(&MatrixAlt::function02, this, threadIndex));
You need to specify the exact class::function and take its address and which instance of the class your doing it for, and then the parameters.
The second problem which you haven't see yet is this line
std::vector<std::future<bool>> threadsIssued;
All those futures will be lost in scope exit, like tears in rain. Time to destroy.
Freely after Blade runner.
All those moments will be lost in time, like tears in rain. Time to
die.
Whenever you have a member function in C++, that function takes the object itself as an implicit first argument. So you need to pass the object as well, but even then, it can't be called with the same syntax as a normal function that takes the object.
The simplest way to setup an asynchronous job in C++ is typically just to use lambdas. They've very clear and explicit. So, for example, you could change your call to:
threadsIssued.push_back(std::async([this] (size_t t) { this->function02(t);}, threadIndex));
This lambda is explicitly capturing the this pointer, which tells us that all of the function02 calls will be called on the same object that the calling function01 is called on.
In addition to being correct, and explicit, this also helps highlight an important point: all of the function02 objects will be running with mutable access to the same MatrixAlt object. This is very dangerous, so you need to make sure that function02 is thread safe, one way or another (usually easy if its conceptually const, otherwise perhaps need a mutex, or something else).
I know that this may be fairly confusing, but I'm writing a unit test using the Boost test framework. I'm trying to simply increment a variable to test that a specific callback was executed as expected.
This is the test code excerpt:
uint32_t nSuccessCallbacks = 0;
uint32_t nFailureCallbacks = 0;
auto successCallback = [&nSuccessCallbacks, this] {
std::cout << "Running success callback...\n";
++nSuccessCallbacks;
};
auto failureCallback = [&nFailureCallbacks, this] (const std::string& str) {
std::cout << "Error code: " << str << "\n";
std::cout << "Running failure callback...\n";
++nFailureCallbacks;
};
dest.advertise(rr, successCallback, failureCallback);
The definition of advertise:
void
NfdRibReadvertiseDestination::advertise(nfd::rib::ReadvertisedRoute& rr,
std::function<void()> successCb,
std::function<void(const std::string&)> failureCb)
{
m_controller.start<ndn::nfd::RibRegisterCommand>(
ControlParameters().setName(rr.getPrefix()).setOrigin(ndn::nfd::ROUTE_ORIGIN_CLIENT).setFlags(ndn::nfd::ROUTE_FLAG_CHILD_INHERIT),
[&] (const ControlParameters& cp) { successCb(); },
[&] (const ControlResponse& cr) { failureCb(cr.getText()); });
}
Just for reference, dest is defined in the test fixture.
I'm not able to modify nSuccessCallbacks. Whenever the callback is called, we step through it correctly, but after the callback exits and we are in code after dest.advertise(), the value is still 0. We successfully reach the callback lambda, but the gdb reports that there is no such variable in the scope. I've tried every reasonable combination of all-capture, specific capture, mixing in the this and removing it, etc. I don't know why the capture clause incorrectly captures the variable. My best guess is that since the lambda is passed into another lambda, the capture clause of the first is lost?
EDIT: The callback is executed when an interface object receives data. We mock that up later in the test, and was unimportant so I chose not to include it.
Using a crystal ball, your lambda is run after one of the many scopes where you capture something by reference (either advertise or your "test code exerpt") has exited. Thus the by-reference captured variable has left scope, and UB results, and you see garbage.
Your code as posted does not actually run the lambda, so clearly the code as posted has no such problem with the lambda containing garbage.
As a general rule, never capture by reference if your lambda or any copies of it could possibly outlive the current scope. Capture by copy, or (in C++14) by move. There are exceptions to this rule, but they are easy sources of bugs.
As a second rule, if your lambda outlives the current scope, explicitly capture everything you capture. Have no default capture. That way you won't be surprised by something being captured whose lifetime (or pointed-to lifetime) is not long enough, like this or some pointer or somesuch.
At the least do this:
[successCb] (const ControlParameters& cp) { successCb(); },
[failureCb] (const ControlResponse& cr) { failureCb(cr.getText()); }
Then ensure that this, and no copies of this:
auto successCallback = [&nSuccessCallbacks, this] {
std::cout << "Running success callback...\n";
++nSuccessCallbacks;
};
does not outlive its scope. If it does, change how you capture.
The start call will, given the name, start an asynchronous thread to process the request. Unfortunately this means that the variables captured by reference in the lambda will have been already deallocated when they're accessed.
C++ only allows you to capture by copy (and you've no lifetime problems) or to capture by reference but you must ensure that the lambda will not outlive the referenced variables.
To solve correctly the "upward funarg" problem (a lambda capturing a variable - not a value - from a context and outliving the context) a garbage collector is needed (a stack isn't enough) and C++ doesn't provide one.
A solution (if you pay attention to avoiding loops) is to capture by value a shared_ptr to the mutable shared state needed.
I'm having a bit of trouble creating a thread in C++. When I attempt to create one I get these two errors...
error C2661: 'std::thread::thread' : no overloaded function takes 2 arguments
error C3867: 'XboxControler::VibreateThread': function call missing argument list; use '&XboxControler::VibreateThread' to create a pointer to member
I've searched the internet but to no avail, I'm not too sure what's causing it and was hoping someone out there can point out where I'm going wrong.
The relevant code to the problem is...
This currently is using 1000 for milliseconds for testing purposes. It creates the thread for a controller vibration so it can last a certain amount of time before stopping.
void XboxControler::Vibrate(int leftVal, int rightVal)
{
std::thread vibThread = std::thread(XboxControler::VibreateThread,vibStruct(leftVal, rightVal, 1000));
}
This is the vibration thread, it starts and stops the controller vibration.
void XboxControler::VibreateThread(vibStruct& vals){
XINPUT_VIBRATION Viberation;
ZeroMemory(&Viberation, sizeof(XINPUT_VIBRATION));
Viberation.wLeftMotorSpeed = vals.leftVal;
Viberation.wRightMotorSpeed = vals.rightVal;
XInputSetState(_controllerNum, &Viberation);
Sleep(vals.milliseconds);
Viberation.wLeftMotorSpeed = 0;
Viberation.wRightMotorSpeed = 0;
XInputSetState(_controllerNum, &Viberation);
}
This is the struct used in the parameter of the thread, there didn't used to be this and it was only added in an attempt to get the thread running properly. It is declared privately in the header file of the this controller class.
struct vibStruct{
int leftVal;
int rightVal;
int milliseconds;
vibStruct(int leftVal, int rightVal, int milliseconds){
vibStruct::leftVal = leftVal;
vibStruct::rightVal = rightVal;
vibStruct::milliseconds = milliseconds;
}
};
Hope that someone can help, I'm sure that there might be a better way of getting the vibration to last a specific time which if you know I would like to hear but for future reference I would also like to know how to solve this specific problem.
EDIT 1:
Thanks for the help everyone, I read through everything said to create the following that works...
I added the & like was pointed out by the complier which I dismissed at first as it still gave me errors. I created a new thread that wouldn't be destroyed once the Vibrate method executes.
void XboxController::Vibrate(int leftVal, int rightVal)
{
new std::thread(&XboxController::ViberateThread, vibStruct(leftVal, rightVal, 1000), _controllerNum);
}
I made the ViberateThread static as suggested and passed in the controller number. I also made the vals a const as way suggested.
void XboxController::ViberateThread(const vibStruct& vals, int controllerNum){
//code...
}
Thanks for the help everyone, I hope my newly amalgamated code isn't breaking any coding practices or making any people weep at some horrible thing I have done :)
P.S. I also noticed the spelling mistakes which have now been fixed so everyone can rest easy.
I have never tried using std::thread but from thread reference -
4) The copy constructor is deleted; threads are not copyable. No two
std::thread objects may represent the same thread of execution.
Your code invokes copy constructor.
std::thread vibThread = std::thread(XboxControler::VibreateThread,
vibStruct(leftVal, rightVal, 1000));
Also, you are trying to bind a rvalue to a non-const reference. So try -
std::thread vibThread(&XboxControler::VibreateThread,
vibStruct(leftVal, rightVal, 1000));
// Note the addition of & operator as compiler suggested
And change -
void XboxControler::VibreateThread(const vibStruct& vals);
//^^^^ notice the const key word
Note I have already looked at the answer found here: Return Double from Boost thread, however the proposed solution doesn't work for me.
I have the following tid-bits of source code
void run(int tNumber, std::vector<char *>files, std::map<std::basic_string,float>word_count)
{
boost::thread_group threads;
std::map<std::basic_string,float> temp;
for(int i = 0; i < tNumber; ++i)
threads.create_thread(boost::bind(mtReadFile,files[i],boost::ref(word_count)));
threads.join_all()
}
This is the function that creates new threads for the calling process. These threads then call an instance of mtReadFile.
void mtReadFile(char *filename, std::map<std::basic_string,float> word_count)
{
//function like things
}
What I need to happen is word_count be returned from each thread to the calling process. I have tried the boost::ref in hopes of getting around the fact that boost threads copy all arguments to thread storage, but it has't worked for me.
Your word_count parameter is passed by value, not by reference:
void mtReadFile(char *filename, std::map<std::basic_string,float> word_count)
instead of
void mtReadFile(char *filename, std::map<std::basic_string,float> &word_count)
This would fail to work even in the single-threaded case, which you should definitely test before attempting the more complex multithreading.
The function needs to accept a reference, AND you need boost::ref() to prevent boost::thread() from copying the parameter before the function invocation.
I am having some problem related to C/C++:
Suppose I have some class
class Demo
{
int constant;
public:
void setConstant(int value)
{
constant=value;
}
void submitTask()
{
// need to make a call to C-based runtime system to submit a
// task which will be executed "asynchronously"
submitTask((void *)&constant);
}
};
// runtime system will call this method when task will be executed
void func(void *arg)
{
int constant= *((int *)arg);
// Read this constant value but don't modify here....
}
Now in my application, I do something like this:
int main()
{
...
Demo objDemo;
for(...)
{
objDemo.setConstant(<somevalue>);
objDemo.submitTask();
}
...
}
Now, hopefully you see the problem as tasks should read the value set immediately before a asynchronous call . As task calls are asynchronous so a task can read wrong value and sometimes results in unexpected behavior.
I don't want to enforce synchronous task execution just because of this constraint. The number of tasks created are not known in advance. I just need to pass this simple integer constant in an elegant way that will work with asynchronous. Obviously I cannot change the runtime behavior (mean that signature of this method void func(void *arg) is fixed).
Thanks in advance.
If you don't want to wait for the C code to finish before you make the next call then you can't reuse the same memory location over and over. Instead, create an array and then pass those locations. For this code, I'm going to assume that the number of times the for loop will run is n. This doesn't have to be known until it's time for the for loop to run.
int* values = new int[n];
for(int i=0;i<n;i++) {
values[i] = <somevalue>;
submitTask((void*)&values[i]);
}
At some later point when you're sure it's all done, then call
delete[] values;
Or, alternately, instead of an array of ints, create an array of Demo objects.
Demo demo[] = new Demo[n];
for(int i=0;i<n;i++) {
demo[i].setConstant(<somevalue>);
demo[i].submitTask();
}
But the first makes more sense to me as the Demo object doesn't really seem to do anything worthwhile. But you may have left out methods and members not relevant to the question, so that could change which option is best. Regardless, the point is that you need separate memory locations for separate values if you don't know when they're going to get used and don't want to wait.