简体   繁体   中英

condition_variable::wait_for method not returning - even after the timeout

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?

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

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
    }
}

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM