shunyo
shunyo

Reputation: 1307

Multithreading - Passing variables between methods of different classes

I am working on a project which requires multithreading. I have three threads two of which run in parallel and one asynchronously as shown in the example code. I have a few questions regarding the variables and boost::shared_mutex

  1. Is there a more elegant approach to pass vectors and other variables between methods?
  2. We are having problems with the boost::shared_mutex in locking critical sections. Is there a better method in this case?

Thank you for your help. Sorry for the length of the code.

// A.h
class A{
private:
       std::vector<int> a_data;
public:
       int capture_a(std::vector<int> &data_transfer,boost::shared_mutex &_access,int &flag);
};

// A.cpp
A::capture_a(std::vector<int> &a_data_transfer,boost::shared_mutex &_access,int &a_flag)
{
     // collect data 
     while(true)
     {
        //data input
        a_data.push_back(data);
        if(a_data.size() > N) //a certain limit
        {
             // save a_data
             a_flag = 1;
             boost::unique_lock< boost::shared_mutex > lock(_access);
             //swap with empty array
             // a_data_transfer should be empty
             a_data_transfer.swap(a_data);
        }
        if(boost::thread_interrupted&)
        {
             std::cout << " Thread interrupted" << std::endl;
             return 0;
        }
     }
}

// B.h
class B{
private:
    std::vector<int> b_data;
public:
    int capture_b(std::vector<int> &b_data_transfer, boost::shared_mutex &_access,int &a_flag,int &b_flag);
};

// B.cpp
B::capture_b(std::vector<int> &b_data_transfer, boost::shared_mutex &_access, int &a_flag,int &b_flag)
{
     // collect data 
     while(true)
     {
        //data input
        b_data.push_back(data);
        if(a_flag == 1) //a_flag is true
        {
             boost::unique_lock< boost::shared_mutex > lock(_access);
             b_data_transfer.swap(b_data);
             b_flag = 1;
             // save data
             a_flag = 0;

        }
        if(boost::thread_interrupted&)
        {
             std::cout << " Thread interrupted" << std::endl;
             return 0;
        }
     }
}

// C.h
class C
{
private: 
      std::vector<int> c_data;
public: 
      int compute_c(std::vector<int> &a_data,std::vector<int> &b_data,boost::shared_mutex &_access, int &b_flag);
}

// C.cpp
C::compute_c(std::vector<int> &a_data,std::vector<int> &b_data,boost::shared_mutex &_access,int &b_flag)
{
    while(true) {
     if(b_flag == 1)
     {
          boost::unique_lock< boost::shared_mutex > lock(_access);
          // compute on c
          c_data = a_data + b_data;    // for example
          // save c_data
          b_flag = 0;
          a_data.clear();
          b_data.clear();
     }
     if(boost::thread_interrupted&)
     {
         std::cout << " Thread interrupted" << std::endl;
         return 0;
     }
   }
}

int main()
{

     std::vector<int> a_data_transfer, b_data_transfer;
     boost::shared_mutex _access;
     int a_flag = 0, b_flag = 0;
     boost::thread t1(&A::capture_a,boost::ref(a_data_transfer),boost::ref(_access),boost::ref(a_flag));
     boost::thread t2(&B::capture_b,boost::ref(b_data_transfer),boost::ref(_access),boost::ref(a_flag),boost::ref(b_flag));
     boost::thread t3(&C::compute_c,boost::ref(a_data_transfer),boost::ref(b_data_transfer),boost::ref(_access),boost::ref(b_flag));
     // Wait for Enter 
     char ch;
     cin.get(ch);

     // Ask thread to stop
     t1.interrupt();
     t2.interrupt();
     t3.interrupt();

     // Join - wait when thread actually exits
     t1.join();
     t2.join();
     t3.join();
}

**********EDIT*************

What I am trying to achieve is:

  1. A and B should run parallelly and when a certain criteria is met in A, the a_data and b_data should be transferred to C. After transferring the data, the vectors should keep on collecting the new data.
  2. C should take in the a_data and b_data and perform a computation when the flag is true.

Problem with boost::shared_mutex - we want the a_data_transfer to be empty when swapping. It happens sometimes but not all the times. I need a way to ensure that happens for the code to run properly.

Upvotes: 0

Views: 108

Answers (1)

jsantander
jsantander

Reputation: 5102

Is there a more elegant approach to pass vectors and other variables between methods?

Well... elegancy is a matter of taste.... But you might want to encapsulate the shared data into some class or struct, containing:

  1. The shared data
  2. the mutex (or mutexes) to protect them
  3. The methods dealing with the shared data and appropriately locking them.

That would simplify the amound of data that you need to pass to the thread execution.

Probably you already know this, but it is important to realize that a thread is not a code element, but just a scheduling concept. The fact that in modern libraries threads are represented by an object it is only for our convenience.

We are having problems with the boost::shared_mutex in locking critical sections. Is there a better method in this case?

Without further details on the actual problems is difficult to say.

Some notes:

  1. shared_mutex is a read/write mutex. Intended to allow multiple simultaneous readers, but only one writer. From the code it seems that you only write (unique_lock), so perhaps you might be able to use a simpler mutex.
  2. In my view, mutexes are introduced to protect pieces of data. And you must take care of locking the minimum amount of time, and only while really accessing the shared data, balancing the need to make a set opertions atomic. You have a single mutex that protects two vectors. That's fine, but you might want to think if that's needed.

Upvotes: 2

Related Questions