2

In my program, I have two basic threads. The first one is the main thread and the second is a Tcp server thread. The TCP server will listen for requests ,and for each request it will create a corresponding thread, each of the newly created threads should start working until they reach a certain point where they have to wait for an indication from the main thread. To solve this issue I am implementing a condition variable using Boost 1.49.

My main problem is whenever any of the newly created threads reach the point of the condition variable my whole program freezes.

For more information, please check: Boost 1.49 Condition Variable issue

Until now I didn't receive any positive response, and I am not able to solve the problem.

Thanks a lot.

Community
  • 1
  • 1
IoT
  • 607
  • 1
  • 11
  • 23

1 Answers1

1

I haven't looked at your other question (too much code)

In general, you have to await/signal a condition under the corresponding mutex, though.

Here's a demonstration using a group of 10 workers that await a start signal:

  • See it Live On Coliru

    #include <boost/thread.hpp>
    #include <boost/optional/optional_io.hpp>
    
    /////////////////////////
    // start condition logic
    
    boost::mutex mx;
    boost::condition_variable cv;
    
    static bool ok_to_start = false; 
    
    void await_start_condition()
    {
        boost::unique_lock<boost::mutex> lk(mx);
        cv.wait(lk, [] { return ok_to_start; });
    }
    
    void signal_start_condition()
    {
        boost::lock_guard<boost::mutex> lk(mx); 
        ok_to_start = true;
        cv.notify_all();
    }
    
    /////////////////////////
    // workers
    static boost::optional<int> shared_secret;
    
    void worker(int id)
    {
        await_start_condition();
    
        // demo worker implementation
        static boost::mutex console_mx;
        boost::lock_guard<boost::mutex> lk(console_mx);
        std::cout << "worker " << id << ": secret is " << shared_secret << "\n";
    }
    
    int main()
    {
        boost::thread_group threads;
    
        for (int i = 0; i<10; i++)
            threads.create_thread(boost::bind(worker, i));
    
        // demo - initialize some state before thread start
        shared_secret = 42;
    
        // signal threads can start
        signal_start_condition();
    
        // wait for all threads to finish
        threads.join_all();
    }
    
  • In case of C++03 you can replace the lambda with a hand-written predicate: Live On Coliru

    namespace /* anon detail */
    {
        bool ok_to_start_predicate() { return ok_to_start; }
    }
    
    void await_start_condition()
    {
        boost::unique_lock<boost::mutex> lk(mx);
        cv.wait(lk, ok_to_start_predicate);
    }
    
  • Or you can use Boost Lambda/Boost Phoenix to do the trick for you: Live On Coliru

    #include <boost/phoenix.hpp>
    void await_start_condition()
    {
        boost::unique_lock<boost::mutex> lk(mx);
        cv.wait(lk, boost::phoenix::cref(ok_to_start));
    }
    
sehe
  • 374,641
  • 47
  • 450
  • 633
  • Thanks for your reply. But I am following exactly the documentation of boost for the usage of the Condition Variable. And in your example your letting all the workers to wait for the Signal to start, but in my case. Each requested is treated in a separate way from the other requests. Each request has its own mutex and condition variable. – IoT Mar 15 '14 at 15:43
  • Maybe you could trim it down to a SSCCE (perhaps use my sample as a starting point?) – sehe Mar 15 '14 at 15:44
  • what d you mean by SSCCE and phoenix? If you want a shorter code regarding my problem, you can check http://stackoverflow.com/questions/22401535/boost-threading-mutex-with-conditional-variable-main-thread-hanging Thanks a lot. – IoT Mar 15 '14 at 16:01
  • You know, I answered ***this*** question. Not some other question. I mean http://www.sscce.org/ and [phoenix](http://www.boost.org/doc/libs/1_55_0/libs/phoenix/doc/html/index.html). Incidentally, the code is right there, in my answer and on Coliru – sehe Mar 15 '14 at 16:07
  • Having looked at the code in the other answer, try moving the `notify_one` call under the mutex (see the comments in my answer). There could be race conditions. Also, use the predicated `wait()` overload exactly as I showed in this example (otherwise, you'll be waiting even if the condition was already set. (There's not enough code to see whether that could actually happen) – sehe Mar 15 '14 at 16:15
  • I used wait() in the same way you said `boost::unique_lock lock(mut); boost::phoenix::cref(ho_complete_indication_received));` But I am still stuck, and the program freezes. The transaction machine which corresponds to a new thread, reaches first to the unique_lock, before the main thread receives an indication for an event will unlock the transaction machine. So is this what do you mean by the race conditions in my case? – IoT Mar 15 '14 at 16:46