Reputation: 722
I'm trying to create a tread from a class member function and initialize said thread through the class constructors initializer list.
Upon execution of thread exception is thrown during the call to Receive_List.push_back(CurVal++)
, however this exception is avoided by simply placing a printf()
as the first instruction in the function.
#include <thread>
#include <list>
class SomeClass
{
std::thread Receive_Thread;
std::list<unsigned int> Receive_List;
void Receive_Main()
{
//printf("Hacky Way Of Avoiding The Exception\n");
const unsigned int MaxVal = 3000;
unsigned int CurVal = 0;
while (CurVal < MaxVal)
{
Receive_List.push_back(CurVal++);
}
}
public:
SomeClass() :
Receive_Thread(std::thread(&SomeClass::Receive_Main, this))
{}
~SomeClass()
{
Receive_Thread.join();
}
void ProcessReceiveList()
{
if (!Receive_List.empty())
{
printf("Received Val: %i\n", Receive_List.front());
Receive_List.pop_front();
}
}
bool IsReceiveEmpty()
{
return Receive_List.empty();
}
};
int main()
{
SomeClass* MyObject = new SomeClass();
//
// Sleep for 1 second to let the thread start populating the list
std::this_thread::sleep_for(std::chrono::seconds(1));
while (!MyObject->IsReceiveEmpty())
{
MyObject->ProcessReceiveList();
}
delete MyObject;
std::system("PAUSE");
return 0;
}
Why is this happening?
Upvotes: 0
Views: 103
Reputation: 254631
The problem you're observing is caused by the thread starting before the list has been initialised, giving a data race, which leads to undefined behaviour. Adding the printf
delays the first access to the list, so that initialisation is more likely to be finished before it's accessed. This does not fix the data race though; it can be fixed by declaring the list before the thread:
std::list<unsigned int> Receive_List;
std::thread Receive_Thread;// WARNING: must be initialised last
You have a further problem: all accesses to data that's modified by one thread and updated by another must be synchronised; usually by guarding it with a mutex. Without synchronisation, you again have a data race, leading to undefined behaviour.
So add a mutex to the class to guard the list:
#include <mutex>
class SomeClass {
std::mutex mutex;
//...
};
and lock it when you access the list
while (CurVal < MaxVal)
{
std::lock_guard<std::mutex> lock(mutex);
Receive_List.push_back(CurVal++);
}
and likewise in the other functions that access the list.
Upvotes: 2