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.
Related
I want to create a cpp program that will have two functions.
void func(int num){
//Assume there are contents here
}
int main(){
int num;
cin >> num
ap(num);
}
The code above works when executed. But I want to use my function func(int num) in a thread.
thread t1(func);
t1.join;
When I use my func() in a thread, in no longer executes. That is why I cannot proceed coding my second function. What is the proper way of passing the value to a function so it can be used in a thread?
I would advise you to take a look at this link: https://www.tutorialcup.com/cplusplus/multithreading.htm
It has many examples and lots of theory to read and understand about threads and multithreading.
Here's a quick outline of my class:
class foo{
public:
vector<string> rawData;
vector<vector<string> > slicedData;
void readData();
void sortData();
private:
static void selectionSort(vector<string>);
};
Basically, readData populates rawData with information from an external file. Once it does this, sortData splits that data into subsets, each of which is stored in slicedData. I need to spawn a thread of selectionSort to sort each subset, and I have to do so inside of sortData.
I've tried it this way within sortData:
thread *threads = new thread[slicedData.size()];
for(int i = 0; i < slicedData.size(); i++){
threads[i] = thread(selectionSort,slicedData[i]);
}
...but when I do so, g++ throws error: attempt to use a deleted function.
For the record, I need to store the threads in an array so I can join them later. I realize this could be done more elegantly with the boost library and thread groups, but I'm trying to keep this project dependency-free.
I couldn't reproduce your error, but the following code compiles for me.
I would recommend using a vector of threads and calling emplace_back() to create the threads inside the vector..
Something like this:
class foo
{
public:
std::vector<std::vector<std::string> > slicedData;
void sortData()
{
std::vector<std::thread> threads;
// for each slice add a new thread passing the function and data
// to its constructor
for(auto& slice: slicedData)
threads.emplace_back(&foo::selectionSort, std::ref(slice));
// NOTE: use of std::ref() to pass by reference
// now join the threads to prevent the threads vector
// going out of scope before they finish
for(auto&& thread: threads)
thread.join();
}
private:
static void selectionSort(std::vector<std::string>&); // pass by reference
};
Also note I pass the data by reference because I suspect you don't really want to sort a copy of the data.
The error isn't in the threading code that you have shown here. Probably, your sortData method doesn't wait for the threads to complete (use thread.join as Galik described), and your foo goes out of scope and gets deleted while the threads are still trying to use it. That's why you see "attempt to use a deleted function"
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);});
}
I've recently started using lambdas an awful lot within threads, and want to make sure I'm not setting myself up for thread-safety issues/crashes later. My usual way of using them is:
class SomeClass {
int someid;
void NextCommand();
std::function<void(int, int)> StoreNumbers;
SomeClass(id, fn); // constructor sets id and storenumbers fn
}
// Called from multiple threads
static void read_callback(int fd, void* ptr)
{
SomeClass* sc = static_cast<SomeClass*>ptr;
..
sc->StoreNumbers(someint,someotherint); // voila, thread specific storage.
}
static DWORD WINAPI ThreadFn(LPVOID param)
{
std::list<int> ints1;
std::list<int> ints2;
auto storenumbers = [&] (int i, int i2) {
// thread specific lambda.
ints1.push_back(i);
ints2.push_back(i2);
};
SomeClass s(id, storenumbers);
...
// set up something that eventually calls read_callback with s set as the ptr.
}
ThreadFn is used as the thread function for 30-40 threads.
Is this acceptable? I usually have a few of these thread-specific lambdas that operate on a bunch of thread specific data.
Thank you!
There's no problem here. A data access with a lambda is no different to a data access with a named function, through inline code, a traditional functor, one made with bind, or any other way. As long as that lambda is invoked from only one thread at a time, I don't see any evidence of thread-related problems.
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.