Trying to start threads of a member function from within a class - c++

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"

Related

How to transfer data between main function and threads?

I want to store the threads that I have created in my main function in an array and later access them in my Thread class. What would be the best way to do this?. Below is the structure of my code.
Main.cpp:
int main(){
//do something
while ((new_socket = socket.Accept())) {
std::thread mythread(&Myclass::MyThread, &myclass,
std::move(new_socket), para1);
// I want to store the above threads created in an array which can later be accessed in a different thread class
}
}
MyClass.cpp
MyClass::MyThread(....){
I want to access the array of threads here.
}
I have tried mutex and cv and add these threads into a queue but it is generating many errors. What is the best way to solve this?
I am not 100% sure if array fits the bill - do you know how many threads there will be?
Maybe a vector is better:
std::vector<std::thread> threads; // could be a member - used to store the threads
while ((new_socket = socket.Accept()))
{
// Construct the thread in place inside the vector
threads.emplace_back(&Myclass::MyThread, &myclass, std::move(new_socket), para1);
}
Now you have all your threads neatly in a vector (note I did not test this with you code because there is not enough of it to test... its not a complete example)

C++ resources allocation with multithreading

I have got a small application and I am using some library via API. This library uses multithreading and I can't figure out how to properly allocate memory.
Let's say I have a class MyClass. This class have a function myFunction and a pointer ptrToSomething. In class's constructor I dynamically create an object (not read-only) and assign it to ptrToSomething, then I work with it in myFunction. And there's only one instance of this class.
With single thread it works fine. But the library I use may call myFunction in different threads. Which means ptrToSomething must be unique for each thread. Oh, and this library uses boost::thread.
So, here's what I do:
I create an array ptrArray of length n (for n threads) and initialize it with objects in the constructor.
Create boost:mutex inside MyClass.
Create std::set<boost::thread::id> idSet for threads ids.
Now in myFunction I lock the mutex, find out the current thread's id with boost::this_thread::get_id(), insert it into idSet, find it's index with std::set::find and std::distance, assign the proper ptrToSomething[idx] to some temp pointer, unlock the mutex and continue with the function.
This code sure works, but I feel it is very inefficient.
Is there a more optimal approach? Or maybe some kind of modifications on the current one?
UPD. Something like this.
class MyClass : public SomeLibraryClass
{
public:
MyObject* ptrToSomething;
mutable std::set<boost::thread::id> threadsIds;
mutable boost::mutex mutex;
MyClass(){
ptrToSomething = new MyObject[threadsNumber];
for(int i = 0; i < threadsNumber; ++i){
ptrToSomething[i] = new MyObject();
}
}
void myFunction() const override{
{
boost::thread::id id = boost::this_thread::get_id();
boost::mutex::scoped_lock scoped_lock(mutex);
threadsIds.insert(id);
std::set<boost::thread::id>::iterator iter = threadsIds.find(id);
int index = std::distance(threadsIds.begin(), iter);
myTempObject = &ptrToSomething[index];
}
// do something
}
}

c++ class method thread [duplicate]

This question already has answers here:
Start thread with member function
(5 answers)
Closed 6 years ago.
i have a class that has a method that needs to be running continuously but also be able to receive input from user. So i thought i would make the method run separately using a thread.
the code looks something like this(just the backbone):
class SystemManager
{
private:
int command;
bool commandAcK;
bool running;
//other vars
public:
SystemManager()
{
//initialisation
}
void runningAlgorithm()
{
while (running)
{
if (commandAcK)
{
//solve command
}
//run algorithm
//print results
}
}
void readCmd()
{
cin >> command;
commandAcK = true;
}
};
int main()
{
SystemManager *SM = new SystemManager;
thread tRunning = SM->runningAlgorithm();
}
now the errors look like this:
no suitable constructor exists to convert from "void" to "std::thread"
Error C2440 'initializing': cannot convert from 'void' to 'std::thread'
i have found a new method and it doesn't give me any errors
std::thread tRunning(&SystemManager::runningAlgorithm, SystemManager());
the first thing i don't understand is that this method doesn't use an instance of the class just the generic function. How can i link it to a specific instance? I need it so it can read the values of the variables.
Secondly what does "&" in front of SystemManager do?
(&SystemManager::runningAlgorithm)
Thirdly is there a better way of doing it? Do you have any ideas?
Thank you in advance.
std::thread tRunning(&SystemManager::runningAlgorithm, SystemManager()); does use an instance of your class. The instance it uses is SystemManager() which is a temporary and only available to the thread. If you need to share the instance then you need to create one yourself and pass it by reference to the thread like
SystemManager sys_manager;
std::thread tRunning([&](){sys_manager.runningAlgorithm();});
And now your call site and your thread have the same instance.
Also note that command and commandAck need to be protected by some sort of synchronization since you can write to them while reading causing a data race and subsequently undefined behavior. Using std::atmoic should work for you.
The constructor for std::thread accepts a functor, and optionally it's arguments. A functor is anything that can be "called" using operator().
Then it starts a thread and inside that thread calls your functor.
std::thread tRunning(&SystemManager::runningAlgorithm, SystemManager());
This will call the member function SystemManager::runningAlgorithm, passing in the only argument being this (SystemManager() creates a temporary instance).
Remember that member functions always accept this as the first argument.
&SystemManager::runningAlgorithm returns the address of the member function runningAlgorithm from the class SystemManager.
In modern C++ this code can be simplified (i.e. made more readable) with a lambda:
std::thread tRunning([]{ SystemManager().runningAlgorithm(); });
The line
thread tRunning = SM->runningAlgorithm();
takes the result of running SM->runningAlgorithm() (a void), and tries to construct a thread from it. If you look at the relevant constructor, though, you can see it needs a function-like argument (with possibly arguments).
One way of running it is through a lambda function:
thread tRunning(
[SM](){SM->runningAlgorithm();});
Two other things to note:
You should join the thread before its destructor is called, in this case:
tRunning.join();
You have a (short lived) memory leak. Why not just create it on the stack?
SystemManager SM;
thread tRunning(
[&](){SM.runningAlgorithm();});
tRunning.join();
Uhm... I guesss you need to study some of the basic concepts of c++, before going multithread.
However... In your code,
thread tRunning = SM->runningAlgorithm();
tries to put the result of your function (that is void... ) inside a variable of type thread... Non likely to be right.
Instead, your second code takes 2 arguments:
std::thread tRunning(
&SystemManager::runningAlgorithm, //a pointer to a method (a pointer to the code of your function, and that is why you use the "&", even though you could have left that out)
SystemManager()); // An instance of the value, built on the stack.
I guest that you are confused by the lack of the word "new" (coming from higher level language?), but that's how it works here:
SystemManager sm = SystemManager(); // <- variable created on the stack, will be automatically destroyed when out of scope
SystemManager *psm = new SystemManager(); // Created in the heap, while in the stack remains just a pointer to it.
//You will need to delete it when done with :
delete psm;
To answer the question
How can i link it to a specific instance? I need it so it can read the values of the variables.
You can do:
int main()
{
SystemManager SM; // = SystemManager(); // <- this is not needed
std::thread tRunning(SystemManager::runningAlgorithm, SM);
// Access SM as you need
// REMEMBER TO CLOSE & JOIN THE THREAD!
tRunning.join();
}
I still think you should first get used to the underlying concepts or it will be really difficult to go on.

vectors and threading in C++

I would like to request for comments/ideas on how to resolve a vector and threading issue that is becoming a bit convoluted. I have researched the issue and have not found a working solution.
The intention is to have 5 person objects (stored in a vector) and then call each of their method to read a book concurrently (hence the threads). The read function contains a never ending loop.
I have the following code(simplified) set up:
class Book{
private:
// some data
public:
// some functions
};
class Person{
private:
// some data vars
int id;
Book abook;
public:
// some functions
Person(int index=0); // constructor
void readBook();
};
int main(void){
vector<Person>PersonsVector;
vector<thread> threads;
int num_of_persons = 5;
for(int i=0; i<num_of_persons; i++){
PersonsVector.push(Person(i)); //create different people
threads.push_back(thread(PersonsVector[i].readBook)); //read book in thread
}
// wait for threads to finnish or kill threads
for(auto& thread: threads)
threads.join();
}
My issue is really in how to call the readBook() function and push this to a thread
threads.push_back(thread(PersonsVector[i].readBook)); //read book in thread
Various variations for example these below lead to errors...
threads.push_back(thread(&PersonsVector[i].Person::readBook, this));
threads.push_back(thread(&Person::PersonsVector[i].Person::readBook, this));
Any ideas how I could resolve this issue?
A pointer-to-method must be called using a combination of a pointer specifying the class and method + an instance of said class on which to invoke said method.
This... thing:
&Person::PersonsVector[i].Person::readBook
actually says...
Get me the class Person,
then a vector within an unspecified instance of Person, which does not contain any such vector...
then an index i within that invalid vector,
then somehow get the constructor of that instance,
then somehow get a method readBook() from within that constructor.
See the problem? That's invalid syntax in so many varied ways.
The correct syntaxes are as follows:
For the pointer-to-method: &Person::readBook
For the instance: PersonsVector[i]
...and you need to give these to std::thread via some mechanism that will bundle the pointer-to-method and instance and make them callable for you - such as a lambda, std::bind, etc. - something like this:
std::thread theThread{
[] // not sure which capture is needed... :/
{
(someInstance.*pointerToMethod)(the, args);
// i.e.
(PersonsVector[i].*readBook)();
}
};
You can use a lambda:
threads.push_back(thread([&PersonsVector[i]])(Person& p){ p.readBook(); });

how to insert vector only once in multiple thread

I have below code snippet.
std::vector<int> g_vec;
void func()
{
//I add double check to avoid thread need lock every time.
if(g_vec.empty())
{
//lock
if(g_vec.empty())
{
//insert items into g_vec
}
//unlock
}
...
}
func will be called by multiple thread, and I want g_vec will be inserted items only once which is a bit similar as singleton instance. And about singleton instance, I found there is a DCLP issue.
Question:
1. My above code snippet is thread safe, is it has DCLP issue?
2. If not thread safe, how to modify it?
Your code has a data race.
The first check outside the lock is not synchronized with the insertion inside the lock. That means, you may end up with one thread reading the vector (through .empty()) while another thread is writing the vector (through .insert()), which is by definition a data race and leads to undefined behavior.
A solution for exactly this kind of problem is given by the standard in form of call_once.
#include<mutex>
std::vector<int> g_vec;
std::once_flag g_flag;
void func()
{
std::call_once(g_flag, [&g_vec](){ g_vec.insert( ... ); });
}
In your example, it could happen that second reentrant thread will find a non empty half initialized vector, that it's something that you won`t want anyway. You should use a flag, and mark it when initialization job is completed. Better a standard one, but a simple static int will do the job as well
std::vector<int> g_vec;
void func()
{
//I add double check to avoid thread need lock every time.
static int called = 0;
if(!called)
{
lock()
if(!called)
{
//insert items into g_vec
called = 1;
}
unlock()
}
...
}