简体   繁体   中英

Lock a vector with a mutex - Boost

I'm writing code for a router and I want to, after receiving a packet on my receiver thread, to store that packet (which is of type "unsigned char *" as of now) in a vector. I have two receiver threads that are linked to two different interfaces, and a receiver thread should only store the packet received if another thread isn't accessing the vector already.

Other than the two receiving threads I will have a main thread processing the packets and two sending threads, one for each interface. Total thread count is 5. To prevent trouble when the different threads are writing or reading from the vector I've come to hear of a mutex, which supposedly should lock the vector for other (in this case) threads until after the thread in question is done reading or writing from the vector.

What I want to know is how this is processed into code. Some examples would be very much appreciated. I'm all pretty new to C++, Boost and Raw Sockets. And to top it off I'm not very fond of using different classes yet in C++. I know very well how they work in Java and C#, but what I've come to find is that C++ is very different (because of the header files). I have all my code in one giant main class, which might not be very good coding style, but that's how it works for now.

Should I create a class (.h and .cpp file) for handling this vector or should I just implement it in my giant main class and if so I would be very happy for some simple examples. Below is an example of how I want my program to work. I already have the RecvThread in place and I am able to print out the MAC Hdr of a packet.

void RecvThread()
{
    //receive a packet


    while(true)
    {
        //get lock status from vector

        if(vector is locked)
        {
            usleep(10000);
        }
        else
        {
            //lock vector
            //save packet in vector
            //unlock vector
        }
    }
}

void SendThread()
{
    while(true)
    {
        //get lock status from vector

        if(vector is locked)
        {
            usleep(10000);
        }
        else
        {
            //lock vector
            //get packet from vector
            //unlock vector
        }
    }

    //send the packet
}

void MainThread()
{

    while(true)
    {
        if(recv vector is empty)
        {
            usleep(10000);
        }
        else if(recv vector is locked)
        {
            usleep(10000);
        }
        else
        {
            //lock recv vector
            //get packet in front of queue
            //unlock recv vector
            //process packet (update different fields)
            //get packet interface (either 1 or 2)
            if(send vector (matching interface) is locked)
            {
                usleep(10000);
            }
            else
            {
                //lock send vector (matching interface)
                //save packet to send vector (matching interface)
                //unlock send vector (matching interface)
            }
        }
    }
}

int main()
{
    //create Recv vector
    //create Send vector 1 and 2 (one for each interface)
    //create and join RecvThread 1 and 2
    //create and join SendThread 1 and 2
    //create and join MainThread
}

Hope this gives you the idea. Didn't test it as it's obviously incomplete :) The key is boost::lock_guard<boost::mutex> lock(mx_); as this line can only be executed by one thread at a time. What's actually happening is that thread A for instance calls this function and since it is the first thread to arrive there boost::lock_guard<boost::mutex> lock(mx_); returns immediately and the thread can proceed into what is called the critical section (code segment after the lock). Basically boost::lock_guard<boost::mutex> lock(mx_); only returns if no other thread is inside the critical section. In case that the critical section is already being accessed by another thread, boost::lock_guard<boost::mutex> lock(mx_); simply doesn't return until the other thread left the critical section. In order for the waiting thread to proceed now, the mutex needs to be unlocked. In boost, this is automatically done once the blocking thread (the first to enter the section) leaves the scope of the function with the critical section. Leaving the scope destroys the variable mx_ which allows another mutex with the same name to be created and locked.

EDIT: You don't specifically lock one variable such as a vector. You lock a segment of your code, where that variable is accessed.

class Receiver{
private:
  boost::mutex mx_;
  int *data_;   // I need protection

public:
  bool receive_data(){
    // Prepare connection and do some stuff...

    void some_function(){
      // Before we access data_, we need to make sure only the current thread does so.
      // Mutex will unlock once the scope of this function is left
      boost::lock_guard<boost::mutex> lock(mx_); 

      // Access data_ here (mutex is locked)
      //....
    } // End of scope and mutex unlocks automatically since it's destroyed
    return true;  // Will unlock the mutex since the function's scope is left. 
  }
};

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM