Encapsulation implements thread library

Encapsulation implements thread library

Thread.hpp==>Writing of open source c++ project header files and source files

Open source code for header only uses .hpp files because it allows class declarations and method implementations to be put together.

System programming and network programming, the bottom layer is C language, and it is destined to use C/C++ mixed compilation, but some system functions require that the parameters passed in do not recognize the string type, so it is recommended that some IO interfaces still use C language.

The role of (void)n

(void)n;Write because assert only takes effect in debug mode, not in release mode. Then n is a variable that is defined but not used, and there will be a warning under some compilers. Here, a harmless operation is performed on n but the warning can be cancelled.

How to choose assert, if, and exception

Use assert when expected, if and exception when unexpected.

Correct way to define thread call function

version 1:

class Thread
{
public:
    typedef std::function<void*(void*)> func_t; //定义了线程要执行的函数类型
public:
    // 创建线程
    void start()
    {
        int n = pthread_create(&_tid, nullptr, func_t, _args); //error
        assert(n == 0); //保证线程创建成功
        (void)n;
    }
private:
    pthread_t _tid; //线程id
    std::string _name; //线程名
    func_t _func; //线程要执行的函数
    void* _args; //线程函数参数
};

Since the function to be executed by the thread we defined is C++ , int n = pthread_create(&_tid, nullptr, func_t, _args);this line of code will report an error, because the system function only recognizes c-type functions , so we think of a way to wrap this function with a c-type shell, version 2 is as follows

class Thread
{
public:
    typedef std::function<void*(void*)> func_t; //定义了线程要执行的函数类型
public:
    void* start_routime(void* args)
    {
        return _func(args);
    }
    // 创建线程
    void start()
    {
        int n = pthread_create(&_tid, nullptr, start_routime, _args); //error
        assert(n == 0); //保证线程创建成功
        (void)n;
    }
private:
    pthread_t _tid; //线程id
    std::string _name; //线程名
    func_t _func; //线程要执行的函数
    void* _args; //线程函数参数
};

int n = pthread_create(&_tid, nullptr, start_routime, _args);This code still reports an error, why? Because the start_routime function is a member of the class at this time, there will be a default parameter, an implicit object pointer this , that is void* start_routime(Thread* this, void* args);, the parameter passed to pthread_create is wrong, so the error is still reported, what is the solution? Add a static modification to get version 3 as follows

class Thread
{
public:
    typedef std::function<void*(void*)> func_t; //定义了线程要执行的函数类型
public:
    static void* start_routime(void* args)
    {
        return _func(args);//error
    }
    // 创建线程
    void start()
    {
        int n = pthread_create(&_tid, nullptr, start_routime, _args); 
        assert(n == 0); //保证线程创建成功
        (void)n;
    }
private:
    pthread_t _tid; //线程id
    std::string _name; //线程名
    func_t _func; //线程要执行的函数
    void* _args; //线程函数参数
};

return _func(args);Start to report an error, because start_routime is a static method, static methods cannot call member methods and member variables of the class, but this cannot be changed here, because the static func_t _func;effect we hope to achieve is that each created thread can perform different tasks, when _func When it is static, it means that the thread created by my packaged thread library will only do one thing. Solution 1 defines the function outside the class, and then uses friends to access the members of the class. Of course, there are other solutions. Next, use the following solution:

class Thread; //声明
class Context //设置一个上下文
{
public:
    Thread* _this;
    void* _args;
public:
    Context(): _this(nullptr), _args(nullptr)
    {}
    ~Context()
    {}
};
class Thread
{
public:
    typedef std::function<void*(void*)> func_t; //定义了线程要执行的函数类型
public:
    static void* start_routime(void* args) //start_routime是类内成员,它的参数会有个this指针,要加个static确保只有1个参数
    {
        Context* ctx = (Context*)args;
        ctx->_this->run(ctx->_args);
        delete ctx;
    }
    void* run(void* args)
    {
        return _func(args);
    }
    // 创建线程
    void start()
    {
        Context* ctx = new Context();
        ctx->_this = this;
        ctx->_args = _args;
        
        int n = pthread_create(&_tid, nullptr, start_routime, ctx); 
        assert(n == 0); //保证线程创建成功
        (void)n;
    }
private:
    pthread_t _tid; //线程id
    std::string _name; //线程名
    func_t _func; //线程要执行的函数
    void* _args; //线程函数参数
};

It is equivalent to wrapping the function called by the thread again. So far, it can be used normally. For all the code, see my gitee library https://gitee.com/hepburn0504-yyq/linux-class/tree/master/2023_03_22_ThreadPackage.

Guess you like

Origin blog.csdn.net/m0_61780496/article/details/129853856