Boost logo

Boost Users :

From: Ruediger Berlich (ruediger.berlich_at_[hidden])
Date: 2008-08-11 08:01:46


Hi there,

at the end of this mail is a small program that starts three threads out of
a fourth one ("thread4"). thread1, 2 and 3 are not allowed to start
execution before a certain condition is met (here: go_ is set to true and
the threads are notified of the changed condition).

The threads increment a variable. Once this variable has reached a threshold
(here: 10), execution is supposed to stop. This is done by calling the
interrupt() function on each thread, which in turn catch the corresponding
exception and act on it.

All this seems to work nicely, except for the fact that the "master thread"
(thread4 in this example) does not seem to get any processing time over a
long period. Hence thread 1,2 and 3 count to a very high number before the
stop condition is met.

Here is the output of the program:

Starting threads
Going to sleep for 2 seconds in startAndStopThreads()
Hello world Nr. 0 from thread 1
Hello world Nr. 1 from thread 2
[...]
Hello world Nr. 6167 from thread 2
Hello world Nr. 6168 from thread 2
Sending interrupt
Received interrupt in thread 3
Received interrupt in thread 1
Received interrupt in thread 2
Done ...

Occasionally the counting can go on up to a few hundred thousand. This is on
a single-processor machine with OpenSUSE 11/64 bit, g++ 4.3.1 and a recent
trunk version of Boost 1.36 .

The situation is much better on a four-processor system with the same
operating system - the counter typically reaches only a few hundred there,
presumably as thread4 gets access to a time slice more quickly (but why
isn't it running permanently on a four processor machine - there are only 4
active threads ?).

Is there anything that can be done to improve the time slices allocated to
thread4 ? I am already calling the yield() function in thread1, 2 and 3.

Thanks and Best Regards,
Ruediger

/*********************************************************************/
#include <iostream>

#include <boost/cstdint.hpp>
#include <boost/bind.hpp>
#include <boost/exception.hpp>
#include <boost/thread/mutex.hpp>
#include <boost/thread/condition.hpp>
#include <boost/thread/condition_variable.hpp>
#include <boost/thread/thread.hpp>

#include <boost/date_time.hpp>

using namespace std;

class test
{
public:
  test()
    :jointData_(0),
     MAXJOINTDATA(10),
     go_(false),
     thread1(boost::bind(&test::sayHello, this, 1)),
     thread2(boost::bind(&test::sayHello, this, 2)),
     thread3(boost::bind(&test::sayHello, this, 3))
  { /* nothing */ }

  void startAndStopThreads(){
    std::cout << "Going to sleep for 2 seconds in startAndStopThreads()" <<
std::endl;
    boost::this_thread::sleep(boost::posix_time::seconds(2));

    boost::unique_lock<boost::mutex> lock(helloMutex_);
    go_=true;
    lock.unlock();
    readyToGo_.notify_all();

    while(true){
      boost::unique_lock<boost::mutex> lock2(helloMutex_);

      if(jointData_ >= MAXJOINTDATA){
        go_=false;

        std::cout << "Sending interrupt" << std::endl;
        thread1.interrupt();
        thread2.interrupt();
        thread3.interrupt();

        break;
      }
    }

    thread1.join();
    thread2.join();
    thread3.join();
  }

  void sayHello(const uint16_t threadNumber){
    while(true){
      boost::unique_lock<boost::mutex> lock(helloMutex_);

      while(!go_) {
        try{
          readyToGo_.wait(lock);
        }
        catch(boost::thread_interrupted&){
          std::cout << "Received interrupt in thread " << threadNumber <<
std::endl;
          return;
        }
      }

      std::cout << "Hello world Nr. " << jointData_++
                << " from thread " << threadNumber << std::endl;

      boost::this_thread::yield();
    }
  }

private:
  volatile uint32_t jointData_;
  const uint32_t MAXJOINTDATA;
  bool go_;

  boost::mutex helloMutex_;
  boost::condition_variable readyToGo_;
  boost::thread thread1, thread2, thread3;
};

main(){
  test Test;

  std::cout << "Starting threads" << std::endl;
  // Test.startAndStopThreads(); // This doesn't make a difference
  boost::thread thread4(boost::bind(&test::startAndStopThreads,&Test));
  thread4.join();

  std::cout << "Done ..." << std::endl;
}


Boost-users list run by williamkempf at hotmail.com, kalb at libertysoft.com, bjorn.karlsson at readsoft.com, gregod at cs.rpi.edu, wekempf at cox.net