Execution object member function in a separate thread

statement of problem

Virtually all threads are used to handle C functions, not C ++ class member functions. The standard library provides an API function that callback function pointer to execute code as a thread and calls the callback function in a separate thread. The problem is you can not create a thread execution object member function in such a thread library; only regular functions. Therefore, the following code is a failure:

// start the thread Thread library function 
int thr_create (void (PF *) (), void * PRM, thread_t * PTH); 

#include "class1.h" 

int FUNC (void * param) 
{ 
thread_t T1; 
// following call cause a compiler error: "of can not convert For '' void (class1 :: *) () '' to '' void (*) () ''" 
// meaning that can not convert the type of 
return thr_create (& class1 :: some_method, param, T1 &); 
}

() Callback function address needs, void * pointer is passed as an argument to the callback function address, passing the parameters as well as a function of the variable thread_t thr_create.

The reason why the above code compilation fails because the first parameter passed to The thr_create () member function is a pointer of class1, instead of the normal function pointer. Conceptually, the general functions and class member functions are two completely different things. Even if the cast does not work. So how to solve this problem?

Solution

Use a static member function

The first solution is to make a static member function callback. Because static member functions without Implicit parameter "this". Thus, the parameters of the address pointer can be regarded as a normal function to be used. If access to an object from a static member function data members, explicitly address to the incoming object. E.g:

Hack class 
{ 
Private: 
int X; 
public: 
int get_x (); 
static void FUNC (Hack * pThis); // static member functions 
void func2 (); // non-static member functions 
}; 

void Hack :: FUNC (Hack * pThis) 
{ 
int Y = pthis-> get_x (); // access object data member 
}

This method can be feasible in most cases, but sometimes can not be declared as static member function, that function is a virtual member function or are using a third-party classes can not be modified. When this happens, a method to solve the problem is more difficult.

Processing non-static member function

Assuming that non-static member function func2 Hack class need to call in a separate thread (). Do not directly address transfer member function to thr_create (), void * argument with a statement of ordinary function intermediary (void *), and then call it:

void intermediary(void*);

Then create a structure, the structure is defined as follows:

A struct 
{ 
Hack * P; // pointer to the class object 
void (Hack :: * pmf) ( ); // member function pointers 
};

Create an instance of the structure, the structure is filled with the desired target address and the address of the member function.

A a; // structure example 
Hack h; // Create Object 
// filling structure 
AP = & H; 
a.pmf Hack :: = & func2; // get member function address

Now go back and implement intermediary () function:

intermediary void (void * PTR) 
{ 
A * PA = static_cast <A *> (PTR); // p is cast * A 
Hack pH = * PA-> p; // Hack extracted from the object address A 
void ( hack :: * pmf) () = pa-> pmf; // member function to extract ptr 
(ph -> * pmf) ( ); // call the member function 
}

Finally, the intermediary () is passed to address thr_create ():

thr_create (intermediary, (void*) &a, &t1 );

The thr_create () function calls the intermediary () and address A is passed to it. intermediary () and then expand its structure pointer parameter A and a desired member function calls. This indirect way of treatment can safely start member function in a separate thread, even the thread library does not support member function. If you need to call a function of the different members of different classes, structures can be converted into class A template will function intermediary () function to convert the template. So the compiler automatically generates the majority of boilerplate code.

Reproduced in: https: //www.cnblogs.com/rogee/archive/2011/03/31/2000495.html

Guess you like

Origin blog.csdn.net/weixin_34217773/article/details/94680667