web123456

C++ Multithreading Implementation

C++ multi-threadedrealization

Recently code code used to multi-threaded, summarize the relevant usage, may not be very comprehensive, just use some of the basics.

1. Simple multithreading implementation

#include <iostream>
#include <>

...

void* function(void)
{
    cout<<"hello world"<<endl;
    return 0;
}

int main()
{
    ...

    int thread_num = 5;
    pthread_t td[thread_num];
    for(int i = 0;i<thread_num;i++)
    {
        int ret = pthread_create(&td[i],NULL,function,NULL);
        if(!ret) cout<<"pthread_create error: error_code ="<<ret<<endl;
    }
    pthread_exit(NULL);
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24

This simple code contains a few of the most basic operations of multithreading. First, you need the id of the thread, then you need to create the thread (pthread_create function), and when you create the thread you need to associate the thread with the function you are calling. Finally, you need to exit the thread.

The pthread_create function has 4 parameters, the first parameter is the id of the thread, the second is the parameters of the thread, usually NULL, the third is the function called by the thread, and the fourth is the parameters of the function called by the thread.

pthread_exit(status) is to show the exit of the calling thread, releasing the resources occupied by the thread. status is the return value of the end of the thread, like the 0 in return 0.

Sometimes pthread_join(pthread_t thread, void * * value_ptr), which is a blocking function, is used. The thread that calls this function hangs until the function completes, and then it continues.

2. Threaded functions passing multiple parameters

Like in the pthread_create function where there is only one return parameter, when the thread function has more than one parameter, the parameters need to be consolidated into a single structure for transmission, as shown in the code below:

...
struct thread_para
{
    var para1;
    var para2;
}

...

void *thread_fun(void* arg)
{
    thread *pstru;
    pstru = (struct thread_para*) arg;
    pstru->para1;
    pstru->para2;
}

struct thread_para pstru;
pthread_create(&td[i],NULL,thread_fun,& (pstru));
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19

3. Threaded functions are class functions

When the thread function is a class function, we find that it reports the errorerror: invalid use of non-static member function This is because the class function we are calling is not a static function, which can usually be solved by modifying the function to be static. For functions that cannot be modified, we can encapsulate them in a static function. The static function calls a function within the class. But this call is problematic, static functions do not have a this pointer, so we need to pass the this pointer as an argument to the static function, put a part of my code, just as the understanding of this concept.

// In-class
void faceboxes::detect2(const cv::Mat& img, std::vector<Detection>& dets) {
/******* omit *****************/
}

static void* faceboxes::thread_detect2(void *threadarg)//This function is a wrapped static function which completes the implementation of the detect2 function.
{
    struct thread_data *my_data;
    my_data = (struct thread_data *) threadarg;

    faceboxes* pthis = my_data->pthis;
    pthis->detect2((*my_data->ROI),(*my_data->det));
}

void faceboxes::thread_detect2_excute(int num , const cv::Mat& img, std::vector<Detection>& dets)  //num is the number of threads
{
    int error;

    td[num].pthis = this;
    td[num].ROI = &img;
    td[num].det = &dets;

    error = pthread_create(&thread_id[num],NULL,thread_detect2,(void*)&td[num]);
    if (error){
        cout << "Error:unable to create thread," << error << endl;
        exit(-1);
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28