How to transfer data between main function and threads? - c++

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)

Related

How to avoid destroying and recreating threads inside loop?

I have a loop with that creates and uses two threads. The threads always do the same thing and I'm wondering how they can be reused instead of created and destroyed each iteration? Some other operations are do inside the loop that affect the data the threads process. Here is a simplified example:
const int args1 = foo1();
const int args2 = foo2();
vector<string> myVec = populateVector();
int a = 1;
while(int i = 0; i < 100; i++)
{
auto func = [&](const vector<string> vec){
//do stuff involving variable a
foo3(myVec[a]);
}
thread t1(func, args1);
thread t2(func, args2);
t1.join();
t2.join();
a = 2 * a;
}
Is there a way to have t1 and t2 restart? Is there a design pattern I should look into? I ask because adding threads made the program slightly slower when I thought it would be faster.
You can use std::async as suggested in the comments.
What you're also trying to do is a very common usage for a Threadpool. I simple header only implementation of which I commonly utilize is here
To use this library, create the pool outside of the loop with a number of threads set during construction. Then enqueue a function in which a thread will go off and execute. With this library, you'll be getting a std::future (much like the std::async steps) and this is what you'd wait on in your loop.
Generically, you'd want to make access to any data thread-safe with mutexs (or other means, there are a lot of ways to do this) but under very specific situations, you'll not need to.
In this case,
so long as the vector isn't being increased in size (doesn't need to reallocate)
Only reading items or only modifying each item at a time in its own thread
the you wouldn't need to worry about synchronization.
Though its just good habit to do the sync anyways... When other people eventually modify the code, they're not going to know your rules and will cause issues.

C++ Threading using 2 Containers

I have the following problem. I use a vector that gets filled up with values from a temperature sensor. This function runs in one thread. Then I have another thread responsible for publishing all the values into a data base which runs once every second. Now the publishing thread will lock the vector using a mutex, so the function that fills it with values will get blocked. However, while the thread that publishes the values is using the vector I want to use another vector to save the temperature values so that I don't lose any values while the data is getting published. How do I get around this problem? I thought about using a pointer that points to the containers and then switching it to the other container once it gets locked to keep saving values, but I dont quite know how.
I tried to add a minimal reproducable example, I hope it kind of explains my situation.
void publish(std::vector<temperature> &inputVector)
{
//this function would publish the values into a database
//via mqtt and also runs in a thread.
}
int main()
{
std::vector<temperature> testVector;
std::vector<temperature> testVector2;
while(1)
{
//I am repeatedly saving values into the vector.
//I want to do this in a thread but if the vector locked by a mutex
//i want to switch over to the other vector
testVector.push_back(testSensor.getValue());
}
}
Assuming you are using std::mutex, you can use mutex::try_lock on the producer side. Something like this:
while(1)
{
if (myMutex.try_lock()) {
// locking succeeded - move all queued values and push the new value
std::move(testVector2.begin(), testVector2.end(), std::back_inserter(testVector));
testVector2.clear();
testVector.push_back(testSensor.getValue());
myMutex.unlock();
} else {
// locking failed - queue the value
testVector2.push_back(testSensor.getValue());
}
}
Of course publish() needs to lock the mutex, too.
void publish(std::vector<temperature> &inputVector)
{
std::lock_guard<std::mutex> lock(myMutex);
//this function would publish the values into a database
//via mqtt and also runs in a thread.
}
This seems like the perfect opportunity for an additional (shared) buffer or queue, that's protected by the lock.
main would be essentially as it is now, pushing your new values into the shared buffer.
The other thread would, when it can, lock that buffer and take the new values from it. This should be very fast.
Then, it does not need to lock the shared buffer while doing its database things (which take longer), as it's only working on its own vector during that procedure.
Here's some pseudo-code:
std::mutex pendingTempsMutex;
std::vector<temperature> pendingTemps;
void thread2()
{
std::vector<temperature> temps;
while (1)
{
// Get new temps if we have any
{
std::scoped_lock l(pendingTempsMutex);
temps.swap(pendingTemps);
}
if (!temps.empty())
publish(temps);
}
}
void thread1()
{
while (1)
{
std::scoped_lock l(pendingTempsMutex);
pendingTemps.push_back(testSensor.getValue());
/*
Or, if getValue() blocks:
temperature newValue = testSensor.getValue();
std::scoped_lock l(pendingTempsMutex);
pendingTemps.push_back(newValue);
*/
}
}
Usually you'd use a std::queue for pendingTemps though. I don't think it really matters in this example, because you're always consuming everything in thread 2, but it's more conventional and can be more efficient in some scenarios. It can't lose you much as it's backed by a std::deque. But you can measure/test to see what's best for you.
This solution is pretty much what you already proposed/explored in the question, except that the producer shouldn't be in charge of managing the second vector.
You can improve it by having thread2 wait to be "informed" that there are new values, with a condition variable, otherwise you're going to be doing a lot of busy-waiting. I leave that as an exercise to the reader ;) There should be an example and discussion in your multi-threaded programming book.

C++ multithreading application crashes

I'm programming a simple 3D rendering engine just to get more familliar with C++. Today I had my first steps with multithreading and already have a problem I cannot wrap my head around. When the application starts it generates a small, minecraft-like terrain consisting of cubes. They're generated withhin the main thread.
Now when I want to generate more chunks
void VoxelWorld::generateChunk(glm::vec2 chunkPosition) {
Chunk* generatedChunk = m_worldGenerator->generateChunk(chunkPosition);
generatedChunk->shader = m_chunkShader;
generatedChunk->generateRenderObject();
m_chunks[chunkPosition.x][chunkPosition.y] = generatedChunk;
m_loadedChunks.push_back(glm::vec2(chunkPosition.x, chunkPosition.y));
}
void VoxelWorld::generateChunkThreaded(glm::vec2 chunkPosition) {
std::thread chunkThread(&VoxelWorld::generateChunk, this, chunkPosition);
chunkThread.detach();
}
void VoxelWorld::draw() {
for(glm::vec2& vec : m_loadedChunks){
Transformation* transformation = new Transformation();
transformation->getPosition().setPosition(glm::vec3(CHUNK_WIDTH*vec.x, 0, CHUNK_WIDTH*vec.y));
m_chunks[vec.x][vec.y]->getRenderObject()->draw(transformation);
delete(transformation); //TODO: Find a better way
}
}
I have my member function (everything is non-static) generateChunk() which generates a Chunk and stores it in the VoxelWorld class. I have a 2D std::map<..> m_chunks which stores every chunk and a std::vector<glm::vec2> m_loadedChunks which stores the positions of the generated chunks.
Calling generateChunk() works fine as expected. But when I try generateChunkThreaded() the application crashes! I tried commenting out the last line of generateChunk(), then it does not crash. Thats what confuses me so much! m_loadedChunks ist just a regular std::vector. I tried making it public, with no effect. Is there anything obvious I miss?
You are accessing m_loadedChunks from several threads without synchronizing it.
You need to lock the usage of shared usages. So few tips here.
Declare a mutex as a member of the class
std::mutex mtx; // mutex for critical section
Use it to lock via a critical section each time you want to access the elements
std::lock_guard lock(mtx);
m_chunks[chunkPosition.x][chunkPosition.y] = generatedChunk;
m_loadedChunks.push_back(glm::vec2(chunkPosition.x, chunkPosition.y));
Hope that helps
When you have many threads access shared resources, you either have those resources available as read-only, atomic, or guarded with a mutex lock.
So, for your m_loadedChunks member variable, you would want to have it wrapped in a lock. For example:
class VoxelWorld
{
// your class members and more ...
private:
std::mutex m_loadedChunksMutex;
}
void VoxelWorld::generateChunk(glm::vec2 chunkPosition)
{
Chunk* generatedChunk = m_worldGenerator->generateChunk(chunkPosition);
generatedChunk->shader = m_chunkShader;
generatedChunk->generateRenderObject();
m_chunks[chunkPosition.x][chunkPosition.y] = generatedChunk;
{
auto&& scopedLock = std::lock_guard< std::mutex >(m_loadedChunksMutex);
(void)scopedLock;
m_loadedChunks.push_back(glm::vec2(chunkPosition.x, chunkPosition.y));
}
}
The scopedLock will automatically wait for a lock and when the code goes out of scope, the lock will be released.
Now note, that I have a mutex for m_loadedChunks and not a generic mutex covering all variables that may be accessed by threads. This is actually a good practice introduced by Herb Sutter in his "Effective Concurrency" courses and on his talks at cppcon.
So, for whatever shared variables you have, use the above example as one means to solve race issues.

Trying to start threads of a member function from within a class

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"

How to use a single object in multiple threads?

I want to use a single object in multiple threads using c++. I know from java that threads share all variables, but it seems that in c++ it is different.
I have the following structure to store the date
Class Flow: has multiple integers
Class UE: has a list<Flow*>
Class FlowTable: has a map<int,UE*>
Now have two threads(Objects: InOutReader and OutInReader), each of them has a FlowTable* and shall read and/or insert data to the FlowTable.
in the main() of my starter I call new FlowTable(), create the threaded objects and give the FlowTable* to them using a setter. But in the end it looks like that the two threads work with different FlowTable objects.
class InOutReader{
public:
start(){
while(true){
//read data from somewhere(tap-interface1)
//extract address from ip packet and tcp/udp header etc
Flow* myflow = new Flow(IPsrc,IPdest);
this->myflowTable->insertFlow(myflow);
}
}
}
class OutInReader{
public:
start(){
while(true){
//read data from somewhere(tap-interface1)
//extract address from ip packet and tcp/udp header etc
Flow* myflow = new Flow(IPsrc,IPdest);
this->myflowTable->existsFlow(myflow);// should return true if a flow with the same data was inserted before
}
}
}
main programm
FlowTable* myflowTable;
startThreadOne(){
InOutReader ior = InOutReader();
ior.setFlowTable(myFlowTable);
ior.start();
}
startThreadtwo(){
InOutReader oir = InOutReader();
oir.setFlowTable(myFlowTable);
oir.start();
}
void main(){
myFlowTable = new FlowTable();
std::thread t1 = std::thread(startThreadOne);
std::thread t2 = std::thread(startThreadtwo);
t1.join();
t2.join();
}
What I have to do to use the same FlowTable Object in multiple threads?
I can't make heads or tails of your explication, but if you want to have the two threads sharing the same dynamically allocated FlowTable, the solution in C++ is incredibly simple:
int
main()
{
FlowTable* sharedFlowTable = new FlowTable();
std::thread t1( startThread1, sharedFlowTable );
std::thread t2( startThread2, sharedFlowTable );
// ...
}
Then declare startThread1 and startThread2 to take a FlowTable* as argument. (This is a lot simpler than in Java; in Java, where you'd have to define one class per thread, deriving from Runnable, and give each class a constructor which took a FlowTable, and copied it to a member variable so that the run function could find it.)
EDIT:
Of course, if the value pointed to by sharedFlowTable really is a FlowTable, and no inheritance and factory functions are involved, you could just make it a local variable in main, rather than a pointer, and pass &sharedFlowTable to the threads. This would be even simpler, and more idiomatic in C++. (And I have to thank #5gon12eder for pointing this out. Embarrassingly, because I'm usually the one arguing against dynamic allocation unless it is necessary.)