Search code examples
c++multithreadingc++11shared-ptr

Thread synchronization between data pointed by vectors of std::shared_ptr


I'm pretty new to concurrent programming and I have a specific issue to which I could not find a solution by browsing the internet..

Basically I have this situation (schematic pseudocode):

void fun1(std::vector<std::shared_ptr<SmallObj>>& v) {
  for(int i=0; i<v.size(); i++)
    .. read and write on *v[i] ..
}

void fun2(std::vector<std::shared_ptr<SmallObj>>& w) {
  for(int i=0; i<w.size(); i++)
    .. just read on *w[i] ..
}


int main() {

 std::vector<std::shared_ptr<SmallObj>> tot;

 for(int iter=0; iter<iterMax; iter++) {
   for(int nObj=0; nObj<nObjMax; nObj++)
      .. create a SmallObj in the heap and store a shared_ptr in tot ..

   std::vector<std::shared_ptr<SmallObj>> v, w;
   .. copy elements of "tot" in v and w ..

   fun1(v);
   fun2(w);
 }

 return 0;
}

What I want to do is operating concurrently spawning two threads to execute fun1 and fun2 but I need to regulate the access to the SmallObjs using some locking mechanism. How can I do it? In the literature I can only find examples of using mutexes to lock the access to a specific object or a portion of code, but not on the same pointed variables by different objects (in this case v and w)..

Thank you very much and sorry for my ignorance on the matter..


Solution

  • I need to regulate the access to the SmallObjs using some locking mechanism. How can I do it?

    Use getters and setters for your data members. Use a std::mutex (or a std::recursive_mutex depending on whether recursive locking is needed) data member to guard the accesses, then always lock with a lock guard.

    Example (also see the comments in the code):

    class SmallObject{
    
        int getID() const{
            std::lock_guard<std::mutex> lck(m_mutex);
            return ....;
        }
    
    
        void setID(int id){
            std::lock_guard<std::mutex> lck(m_mutex);
            ....;
        }
    
        MyType calculate() const{
            std::lock_guard<std::mutex> lck(m_mutex);
    
            //HERE is a GOTCHA if `m_mutex` is a `std::mutex`
            int k = this->getID();               //Ooopsie... Deadlock
    
            //To do the above, change the decaration of `m_mutex` from
            //std::mutex, to std::recursive_mutex
    }
    
    private:
        ..some data
        mutable std::mutex m_mutex;
    };