Reputation: 81
I come from C# coding experience; I am beginning to learn C++ and make use of boost libraries for threading. I wrote the following class - trying to execute a member function as a thread. Writing the following simple code, i would expect the while loop inside the thread function to execute every second.
#include <boost/chrono/chrono.hpp>
#include <boost/thread/thread.hpp>
#include <iostream>
using namespace boost;
class MyClassWithThread : public boost::enable_shared_from_this<MyClassWithThread>
{
mutex muThreadControl;
condition_variable cvThreadControl;
bool threadToBeStopped = false;
void ThreadFunction()
{
std::cout << "Beginning the Thread" << std::endl;
while(true)
{
bool endIOThread = false;
std::cout << "\nChecking if Thread to be stopped: ";
{
boost::mutex::scoped_lock lock(muThreadControl);
endIOThread = cvThreadControl.wait_for(lock,
boost::chrono::seconds(1),
[this]{return threadToBeStopped;} ) == cv_status::no_timeout;
std::cout << endIOThread << std::endl
}
}
std::cout << "Exiting the Thread" << std::endl;
}
public:
thread threadRunner;
MyClassWithThread()
{
threadRunner = thread(&MyClassWithThread::ThreadFunction, this);
}
};
int main(int argc, char* argv[])
{
MyClassWithThread myclassWithThread;
myclassWithThread.threadRunner.join();
return 0;
}
To build on Linux:
g++ -std=c++11 -pthread cond-wait-test.cpp -o cond-wait-test -lboost_system -lboost_thread -lboost_chrono
However, when i execute the code, all i notice is that the thread execution is blocked at the call to wait_for method; forever. despite the timeout period. Further, the resource monitor of the system shows a processor core is being 100% utilized.
Could anyone please explain whats happening in the code?
Upvotes: 1
Views: 2006
Reputation: 81
As suggested by @Zan Lynx, the culprit was #pragma pack statement. I initially used only #pragma pack(1) to byte align some structures. This affected many of mutex structures to 1 byte alignment.
I changed the #pragma pack(1) statements to #pragma pack(push, 1) #pragma pack(pop). Its all working fine. Hence my problem is solved; i learnt something. Thanks a Lot. ! :-)
Upvotes: 2
Reputation: 54393
I copied your code and tried it on Linux.
Your code as posted will not compile. I wonder if you tried it?
The problem is that wait_for
with the predicate overload returns a bool
not a cv_status
. The inner loop times out, calls the predicate and returns.
Your code works as expected if I remove the predicate lambda. It also works if I leave the lambda and remove the ==
comparison with the cv_status
.
Perhaps if you do what I did and remove the using namespace boost;
line and then make all Boost objects explicit.
Here is my modified version which works for me:
#include <boost/chrono/chrono.hpp>
#include <boost/thread/thread.hpp>
#include <iostream>
class MyClassWithThread : public boost::enable_shared_from_this<MyClassWithThread>
{
boost::mutex muThreadControl;
boost::condition_variable cvThreadControl;
bool threadToBeStopped = false;
void ThreadFunction()
{
std::cout << "Beginning the Thread" << std::endl;
while(true)
{
bool endIOThread = false;
std::cout << "\nChecking if Thread to be stopped: ";
{
boost::mutex::scoped_lock lock(muThreadControl);
#if 1
endIOThread = cvThreadControl.wait_for(lock,
boost::chrono::seconds(1),
[this]{return threadToBeStopped;} );
#else
endIOThread = cvThreadControl.wait_for(lock,
boost::chrono::seconds(1)) == boost::cv_status::no_timeout;
std::cout << endIOThread << std::endl;
#endif
}
}
std::cout << "Exiting the Thread" << std::endl;
}
public:
boost::thread threadRunner;
MyClassWithThread()
{
threadRunner = boost::thread(&MyClassWithThread::ThreadFunction, this);
}
};
int main(int argc, char* argv[])
{
MyClassWithThread myclassWithThread;
myclassWithThread.threadRunner.join();
return 0;
}
Linux GCC build command:
g++ -std=c++11 -pthread cond-wait-test.cpp -o cond-wait-test -lboost_system -lboost_thread -lboost_chrono
Upvotes: 0
Reputation: 2124
Your program will never exit your while loop.
Solution.
Add some kind of termination condition.
bool endIOThread = false;
while(!endIOThread)
{
std::cout << "\nChecking if Thread to be stopped: ";
{
boost::mutex::scoped_lock lock(muThreadControl);
endIOThread = cvThreadControl.wait_for(lock,
boost::chrono::seconds(1),
[this]{return threadToBeStopped;} ) == cv_status::no_timeout;
std::cout << endIOThread << std::endl
}
}
Upvotes: 0