c++ class method thread [duplicate] - c++

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.

Related

Why do I get "Segmentation fault (core dumped)" error when trying to implement multithreading in c++?

I have a main file where I plan to initiate the threads for my c++ program, for now, I only want to get one of the threads up and running before moving on to the others, but that is proving to be difficult. The purpose of the threads is for a TCP Server and Client to run at the same time, I have already tested my TCP code and it works, the issue now is running each one in its own thread. The following shows my main.cpp code:
#include <thread>
#include <iostream>
#include <functional>
#include "./hdr/tcpip_server.hpp"
#include "./hdr/tcpip_client.hpp"
using namespace std;
tcpServer *backendServer;
//This is done because the callback function of std::thread tcpip_server_thread complains when I only use 'backendServer->Monitor' as my callback function
void StartThread (void) {backendServer->Monitor();}
int main (void)
{
/*Initiate and start TCP server thread*/
std::thread tcpip_server_thread; // done to define object to be used outside the scope of the if statement below
if (backendServer->Init())
{
std::thread tcpip_server_thread (StartThread);
}
/*Initiate and start data reader thread*/
//std::thread tcpip_client_thread (tcpip_client);
tcpip_server_thread.join();
//tcpip_client_thread.join();
return 0;
}
The backendServer class is as follows:
class tcpServer
{
private:
int listening;
sockaddr_in hint;
sockaddr_in client;
socklen_t clientSize;
int clientSocket;
char host[NI_MAXHOST];
char service[NI_MAXSERV];
char buf[4096];
public:
bool Init ();
void Monitor ();
};
The only error I am getting with this code is the one in the title, and I only get it when the code is executing, no errors are received while compiling the code.
When trying the following:
std::thread tcpip_server_thread (backendServer->Monitor);
I get the following warning:
a pointer to a bound function may only be used to call the function
and
no instance of constructor "std::thread::thread" matches the argument list
Any help would be appreciated as this is my first project implementing threads.
1. Initializing backendServer:
backendServer is a pointer to tcpServer, but it is uninitialized (and does not point to any valid object).
Therefore backendServer->Init(); invokes UB Undefined Behavior, and likely to crash.
If you must use a pointer you must allocate it. Better still use a smart pointer like std::unique_ptr instead.
But in your case I believe the best solution is not to use a pointer at all, and define backendServer as a local variable in main:
int main(void)
{
tcpServer backendServer;
// ...
}
This will require accessing it with backendServer. instead of backendServer->.
2. The thread issue:
At the moment, you have 2 tcpip_server_thread variables.
The 2nd one inside the if is shadowing the 1st one you have before.
When you get out of the if's scope, the 2nd tcpip_server_thread will be destroyed, and a std::thread must be joined before destruction.
Later on you attempt to join the 1st one which has not even started, causing a 2nd problem.
In order to fix it:
Inside the if, do not declare a new variable. Instead use the one you already have:
tcpip_server_thread = std::thread(StartThread);
If you made backendServer a local in main as suggested above, you can use a lambda that captures it by reference:
tcpip_server_thread = std::thread(
[&backendServer]() { backendServer.Monitor();});
//--------------^^^^^^^^^^^^^^---------------------------------
Before you join the thread check that it is joinable. In the current code this will not be the case if you didn't enter the if that started the thread:
if (tcpip_server_thread.joinable())
{
tcpip_server_thread.join();
}
A side note: Why is "using namespace std;" considered bad practice?.
The main issue of your code is an uninitialised (actually: zero-initialised) pointer:
tcpServer *backendServer;
Note that you never assign a value to! This results in (as a global variable) the pointer being initialised to nullptr, which you dereference illegally later on, e.g. at (the first time during the programme run)
if (backendServer->Init())
which most likely caused the crash. A quick and dirty fix might look as:
int main()
{
backendServer = new tcpServer(); // possibly with arguments, depending
// on how your constructor looks like
// the code you have so far
delete backendServer; // avoid memory leak!!!
return 0;
}
You spare all this hassle around manual memory management (-> explicit delete) if you use smart pointers instead, e.g. std::unique_ptr. However unless you possibly want to dynamically exchange the backend server, limit its life-time to anything else than the entire programme run or construct it with arguments that need to be retrieved/calculated within main before (none of appears pretty likely to me in given case) then you most likely are better off with a global object:
tcpServer backendServer; // note the dropped asterisk!
This way the object is created before entering main and correctly destructed after leaving.
As now no pointer any more you now refer to members via . instead of ->, i.e. backendServer.Monitor() for instance.
You actually can construct a std::thread with member function pointers, too. You need, though, to pass the object on which this member function should get called to the thread as well:
std::thread(&tcpServer::Monitor, backendServer);
This works with both functions and objects, the latter are accepted by value, though, thus if you use a global object as recommended above you might rather want to create a pointer:
std::thread(&tcpServer::Monitor, &backendServer);
// ^ (!)
// note: NOT if your variable remains a pointer!!!
This way you can actually spare the global variable entirely and create the object within main and the StartThread (actually you should better have named it RunThread) gets entirely obsolete as well.
Alternatives to are converting Monitor function into an operator() or adding such one as
void tcpServer::operator()()
{
this->Monitor();
}
which makes the object itself callable, thus you could pass it directly to the thread's constructor (std::thread(std::ref(backendServer)); with std::ref preventing the object getting copied) or using a lambda:
std::thread([&]() { backendServer.Monitor(); });
both with the same advantage as providing the member function that you can spare global variable and StartThread function.
Still your code reveals another problem:
if (backendServer->Init())
{
std::thread tcpip_server_thread(StartThread);
}
You create here a second local variable tcpip_server_thread which, as long as it exists, hides the previous one, but which runs out of scope and thus gets destructed again right after the end of the if-body!
Instead you want to assign the newly created thread to the already existing variable, which would look like:
tcpip_server_thread = std::thread(StartThread);
Actually you get nicer code if you move the entire thread-code into the if block:
// no thread code left here any more
if(backendServer->Init())
{
std::thread tcpip_server_thread(StartThread);
// start second thread here, too!
tcpip_server_thread.join();
}
// no thread code left here any more
Finally you should not join a thread that actually has failed to start. You spot this by checking if the thread is joinable
std::thread tcpip_server_thread (StartThread);
if(tcpip_server_thread.joinable())
{
// see above for correct construction!
std::thread tcpip_client_thread(tcpip_client);
if(tcpip_client_thread.joinable())
{
tcpip_server_thread.join();
}
else
{
// you might need some appropriate error handling like
// printing/logging a warning message
// and possibly stop the server thread
}
}
else
{
error handling, see above
}
To fix the code I had to do 2 things, one was to not define the tcpServer variable, backendServer, as a pointer, since I never pointed it toward an actual object of the type tcpServer.
Next, I removed the first tcpip_server_thread variable and made sure that the code that initiates ```tcpip_server_thread`` and the code that joins it is in the same scope. In the future, I will implement the std::move function as explained by #wohlstad.
My working code:
#include <thread>
#include <iostream>
#include <functional>
#include "./hdr/tcpip_server.hpp"
#include "./hdr/tcpip_client.hpp"
using namespace std;
/*All the threads*/
tcpServer backendServer;
void StartThread (void) {backendServer.Monitor();}
int main (void)
{
/*Initiate and start tcp server thread*/
if (backendServer.Init())
{
std::thread tcpip_server_thread (StartThread);
if (tcpip_server_thread.joinable())
{
tcpip_server_thread.join();
}
else
{
cout << "error";
}
}
return 0;
}

Multi Threading in c++

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).

Visual Studio 2015 “non-standard syntax; use '&' to create pointer for member”

While creating thread using CreateThread() in Win32 Application , I am getting this error .
In CreateThread(NULL,0,pSample->Resize(),NULL,0,NULL); It shows error in function calling .
I do have several files as :
Main.cpp
WinMain()
{
//Create sample
return Win32Appliaction::Run(&sample);
}
Win32Application.cpp
int Win32Application::Run(DXSample* pSample)
{
//Create Window
pSample->Init();
pSample->Render();
CreateThread(NULL,0,pSample->Resize,NULL,0,NULL);//error occurs
pSample->Destroy();
}
DXSample.h
class DXSample
{
public:
virtual void Init() =0; //and rest all functions
};
HelloTexture.h
class HelloTexture:public DXSample
{
public :
virtual void Init();//all other functions similarly
}
HelloTexture.cpp
void Hellotexture::Init()
{ //code
}
void Hellotexture::Resize()
{
//code
}
Parameter #2 of the CreateThread must be a pointer to function matching ThreadProc signature. You can not pass result of pSample->Resize() (which is void) or a pointer to Resize function itself (because this is a non-static class member function). Also you may want to use ::std::thread instead of calling WinApi directly.
You are calling the pSample->Resize() function, passing the returned value to the CreateFunction as the function to run.
If you want the Resize function to be run in its own thread there are two things you need to do:
Pass a pointer to the function instead, e.g. &HelloTexture::Resize.
Make the function static.
The first point is about passing a pointer to the function itself to CreateThread, who will create the thread and call the function from the new thread.
The second point is because non-static member function needs an object, an instance of the class to be called on.
There are also another problem with the code you have. Remember that threads are running parallel to each other. If you create a thread it will run independently from other threads. That means the object you use, and all its data, must be kept alive until the end of the thread.
I'm bringing this up because you seemingly want to create the thread, and then immediately call pSample->Destroy() which is like pulling the rug out from under some other persons feet.
Do you really want to create a thread here?

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(); });

Trouble tracking down a Bus Error/Seg Fault in C++ and Linux

I have a program that processes neural spike data that is broadcast in UDP packets on a local network.
My current program has two threads a UI thread and a worker thread. The worker thread simply listens for data packets, parses them and makes them available to the UI thread for display and processing. My current implementation works just fine. However for a variety of reasons I'm trying to re-write the program in C++ using an Object Oriented approach.
The current working program initialized the 2nd thread with:
pthread_t netThread;
net = NetCom::initUdpRx(host,port);
pthread_create(&netThread, NULL, getNetSpike, (void *)NULL);
Here is the getNetSpike function that is called by the new thread:
void *getNetSpike(void *ptr){
while(true)
{
spike_net_t s;
NetCom::rxSpike(net, &s);
spikeBuff[writeIdx] = s;
writeIdx = incrementIdx(writeIdx);
nSpikes+=1;
totalSpikesRead++;
}
}
Now in my new OO version of the program I setup the 2nd thread in much the same way:
void SpikePlot::initNetworkRxThread(){
pthread_t netThread;
net = NetCom::initUdpRx(host,port);
pthread_create(&netThread, NULL, networkThreadFunc, this);
}
However, because pthead_create takes a pointer to a void function and not a pointer to an object's member method I needed to create this simple function that wraps the SpikePlot.getNetworSpikePacket() method
void *networkThreadFunc(void *ptr){
SpikePlot *sp = reinterpret_cast<SpikePlot *>(ptr);
while(true)
{
sp->getNetworkSpikePacket();
}
}
Which then calls the getNetworkSpikePacket() method:
void SpikePlot::getNetworkSpikePacket(){
spike_net_t s;
NetCom::rxSpike(net, &s);
spikeBuff[writeIdx] = s; // <--- SegFault/BusError occurs on this line
writeIdx = incrementIdx(writeIdx);
nSpikes+=1;
totalSpikesRead++;
}
The code for the two implementations is nearly identical but the 2nd implementation (OO version) crashes with a SegFault or BusError after the first packet that is read. Using printf I've narrowed down which line is causing the error:
spikeBuff[writeIdx] = s;
and for the life of me I can't figure out why its causing my program to crash.
What am I doing wrong here?
Update:
I define spikeBuff as a private member of the class:
class SpikePlot{
private:
static int const MAX_SPIKE_BUFF_SIZE = 50;
spike_net_t spikeBuff[MAX_SPIKE_BUFF_SIZE];
....
}
Then in the SpikePlot constructor I call:
bzero(&spikeBuff, sizeof(spikeBuff));
and set:
writeIdx =0;
Update 2: Ok something really weird is going on with my index variables. To test their sanity I changed getNetworkSpikePacket to:
void TetrodePlot::getNetworkSpikePacket(){
printf("Before:writeIdx:%d nspikes:%d totSpike:%d\n", writeIdx, nSpikes, totalSpikesRead);
spike_net_t s;
NetCom::rxSpike(net, &s);
// spikeBuff[writeIdx] = s;
writeIdx++;// = incrementIdx(writeIdx);
// if (writeIdx>=MAX_SPIKE_BUFF_SIZE)
// writeIdx = 0;
nSpikes += 1;
totalSpikesRead += 1;
printf("After:writeIdx:%d nspikes:%d totSpike:%d\n\n", writeIdx, nSpikes, totalSpikesRead);
}
And I get the following output to the console:
Before:writeIdx:0 nspikes:0 totSpike:0
After:writeIdx:1 nspikes:32763 totSpike:2053729378
Before:writeIdx:1 nspikes:32763 totSpike:2053729378
After:writeIdx:1 nspikes:0 totSpike:1
Before:writeIdx:1 nspikes:0 totSpike:1
After:writeIdx:32768 nspikes:32768 totSpike:260289889
Before:writeIdx:32768 nspikes:32768 totSpike:260289889
After:writeIdx:32768 nspikes:32768 totSpike:260289890
This method is the only method where I update their values (besides the constructor where I set them to 0). All other uses of these variables are read only.
I'm going to go on a limb here and say all your problems are caused by the zeroing out of the spike_net_t array.
In C++ you must not zero out objects with non-[insert word for 'struct-like' here] members. i.e. if you have an object that contains a complex object (a std string, a vector, etc. etc.) you cannot zero it out, as this destroys the initialization of the object done in the constructor.
This may be wrong but....
You seemed to move the wait loop logic out of the method and into the static wrapper. With nothing holding the worker thread open, perhaps that thread terminates after the first time you wait for a UDP packet, so second time around, sp in the static method now points to an instance that has left scope and been destructed?
Can you try to assert(sp) in the wrapper before trying to call its getNetworkSpikePacket()?
It looks like your reinterpret_cast might be causing some problems. When you call pthread_create, you are passing in "this" which is a SpikePlot*, but inside networkThreadFunc, you are casting it to a TetrodePlot*.
Are SpikePlot and TetrodePlot related? This isn't called out in what you've posted.
If you are allocating the spikeBuff array anywhere then make sure you are allocating sufficient storage so writeIdx is not an out-of-bounds index.
I'd also check that initNetworkRxThread is being called on an allocated instance of spikePlot object (and not on just a declared pointer).