Search code examples
c++boostboost-thread

trouble with boost error lock


I can't figure out where is the problem with this simple code, I think that here is the trouble with output to Console maybe deadlock or something, can somebody, please help.

#include <iostream>
#include <string>
#include <sstream>
#include <boost/thread.hpp>

using namespace std;
struct IntegrateTask
{
   int id;
   double from, to, step, result;

   IntegrateTask(int id, double from, double to, double step)
   {
       this -> id;
       this -> from = from;
       this -> to = to;
       this -> step = step;
   }

   ~IntegrateTask()
   {}
};

vector<IntegrateTask> * tasks = new vector<IntegrateTask>();
boost::mutex mutlist;
boost::mutex iomutex;
boost::condition_variable condtask;

bool isInterrupted = false;

double foo(double x)
{
    return x * x;
}

void integrate(IntegrateTask * task)
{
   double result = 0;
   double step = task -> step;
   for(double i = task -> from ; i != task -> to; i =+ step)
   {
       result += foo(i) * step;
   }
   task -> result = result;
}

void integrateThread()
{

   boost::thread::id id = boost::this_thread::get_id();

   try
   {
       {
           boost::mutex::scoped_lock iolock(iomutex);
           cout << "Thread #" << id << " is working!" << endl;
       }
       while(!isInterrupted)
       {
           IntegrateTask * currtask = NULL;

           {
               boost::mutex::scoped_lock lock(mutlist);                  
               while(!isInterrupted && tasks -> empty())
               {
                   condtask.wait(lock);
               }
               if (!tasks -> empty())
               {
                   currtask = &tasks->back();
                   tasks->pop_back();
               }    
           }
           if (currtask != NULL)
           {
               integrate(currtask);
               boost::mutex::scoped_lock iolock(iomutex);    
               cout << "Task #" << (currtask->id) << "; result = " << (currtask->result) << endl;     
           }
       }
       boost::mutex::scoped_lock iolock(iomutex);
       cout << "Thread # " << id << " stoped working normal!" << endl;    
   }
   catch(boost::thread_interrupted)
   {
       boost::mutex::scoped_lock ioLock(iomutex);
       cout << "Thread # " << id << " stoped working by interruption!" << endl;
   }
   catch(exception & e)
   {
       boost::mutex::scoped_lock iolock(iomutex);
       cout << "Error: " << e.what() << endl;        
   }
}

int main()
{

   cout << "Function for integration: f(x)=x*x" << endl;
   cout << "For stopping program press EXIT" << endl;

   int thcount = 6;// or boost::thread::hardware_concurrency()
   boost::thread_group thgroup;
   for (int i = 1; i <= thcount; i++){
       thgroup.create_thread(&integrateThread);
   }

   int id = 0;

   while (true)
   {
       string line;
       {
           boost::mutex::scoped_lock iolock(iomutex);
           cout << "Task #" << ++id << "; left bound, right bound and step: ";
           getline(cin, line);
       }

       if (line.find("e") != string::npos)
       {
           isInterrupted = true;
           condtask.notify_all();
           thgroup.interrupt_all();
           thgroup.join_all();    
           return 0;
       }

       double from, to, step;
       istringstream input(line);
       input >> from >> to >> step;    

       IntegrateTask * task = new IntegrateTask(id, from, to, step);        
       {
           boost::mutex::scoped_lock lock(mutlist);
           tasks->push_back(*task);            
       }    
       condtask.notify_one();    
   }

}

Solution

  • I haven't tried to follow the logic of what you're aiming to achieve here, but there are 2 issues (at least):

    1. You're not using id in IntegrateTask's constructor. You should generally favour initialisation lists over assignments in constructor bodies, and using class member variable names in function signatures is a recipe for disaster too, so I'd change your constructor to:

      IntegrateTask(int id_init, double from_init, double to_init, double step_init)
          : from(from_init), to(to_init), step(step_init), id(id_init) {}
      
    2. The probable cause of the hanging is your use of != in the for loop in integrate. If you change that to < your program shouldn't hang, but I'm not sure if this breaks your program's logic.