C++ 程序设计:线程基类

1.用C语言中的线程封装一个C++线程基类

线程基类的优点

  1. 灵活性:可被继承的线程基类可以灵活地根据具体需求进行扩展和定制。你可以在派生类中添加额外的成员函数、成员变量,以及自定义的线程操作接口。这使得你可以更好地适应复杂的应用需求。

  2. 可定制性:通过可被继承的线程基类,你可以实现自己的线程管理策略、线程间通信机制等。你可以定义自己的线程调度算法,控制线程的执行顺序和优先级等。这样可以更好地满足特定场景下的需求。

  3. 可扩展性:当你的应用需要多线程之间的协作和通信时,你可以在可被继承的线程基类中定义线程间的通信机制,例如消息队列、互斥锁、条件变量等。这样可以更方便地在多线程环境中实现数据的共享和同步。

  4. 易于维护:使用可被继承的线程基类,你可以将线程相关的代码封装在一个类中,并在该类中提供统一的接口和操作。这使得代码更模块化、可读性更好,并且易于维护和调试。

std::thread 的相对缺点 

当继承std::thread类时会面临一些潜在问题,主要是由于std::thread类的设计和语义的限制导致的。下面是几个需要考虑的问题:

  1. 缺乏虚析构函数:std::thread类没有虚析构函数,这意味着当你使用继承方式时,如果基类的指针指向派生类对象,并且在派生类对象上调用delete操作符,只会调用基类的析构函数,而不会调用派生类的析构函数。这可能导致资源泄漏或未定义的行为。

  2. 禁止复制和移动:std::thread类禁止了复制和移动语义,也就是说,你不能直接复制或移动派生类的实例。这可能限制了一些你希望在派生类中使用的语言特性,例如容器中存储派生类对象或者将派生类对象作为函数参数传递。

  3. 不可继承的成员函数:std::thread类提供了一些成员函数,如join()、detach()等,这些函数不能被派生类继承或重载。因此,在派生类中无法直接重写这些函数,而只能通过其他方式来实现类似的功能。

以下是使用pthread重新编写的c++线程基类

freertos,rtos也可以用相同的方法来实现

/**
  ******************************************************************************
  * @file    threadbase.cpp
  * @author  cj
  * @version V1.0
  * @date    2021/10
  * @brief
  ******************************************************************************
  * @attention

  ******************************************************************************
  */

#include "threadbase.h"
#include "typedef.h"
#include 

ThreadBase::ThreadBase() :
    tid(0)
{

}

ThreadBase::~ThreadBase()
{
    printf("~ThreadBase\n");
}

bool ThreadBase::start()
{
    int ret = 0;

    ret = pthread_attr_init(&t_attr);
    if(ret != 0)
    {
        perror("pthread_attr_init");
        return false;
    }

    /* Sets the stack size for the thread */
    /*
    ret = pthread_attr_setstacksize(&t_attr, max_pthread_size);
    if(ret != 0)
    {
        perror("pthread_attr_getstacksize");
        return false;
    }
    */

    ret = pthread_create(&tid, &t_attr, work, this);
    if(ret != 0)
    {
        perror("pthread_create");
        return false;
    }

    return true;
}

void ThreadBase::routine()
{

}

pthread_t ThreadBase::self()
{
    if(!tid)
    {
        tid = pthread_self();
    }

    return tid;
}

int ThreadBase::equal(pthread_t t)
{
    int ret = 0;
    ret = pthread_equal(tid, t);
    return (ret)?0:-1;
}

int ThreadBase::detach()
{
    return pthread_detach(tid);
}

int ThreadBase::join(pthread_t t)
{
    return pthread_join(t, NULL);
}

int ThreadBase::exit()
{
    int ret = 0;
    pthread_exit(NULL);
    return ret;
}

int ThreadBase::cancel(pthread_t t)
{
    return pthread_cancel(t);
}

int ThreadBase::destroy()
{
    return cancel(tid);
}

void ThreadBase::cleaner(void *pHandle)
{
    ThreadBase *p = (ThreadBase *)pHandle;
    delete p;
    p = NULL;
    printf("after clean\n");
}

void *ThreadBase::work(void *pHandle)
{
    ThreadBase* pThread = (ThreadBase *)pHandle;

    /* Register thread handling functions */
    pthread_cleanup_push(cleaner, pHandle);

    /* Thread-run function */
    pThread->routine();

    /* The thread resource is released. The parameter is non-0 */
    pthread_cleanup_pop(1);

    return NULL;
}
#ifndef THREADBASE_H
#define THREADBASE_H

#include 

class ThreadBase
{
public:
    ThreadBase();
    virtual ~ThreadBase();
    virtual bool start();            // Starting a thread
    virtual void routine();          // running function of a thread, implemented by a derived class
    virtual pthread_t self();        // Get the thread number of the current thread
    virtual int equal(pthread_t t);  // Compares whether the thread numbers are equal
    virtual int detach();            // Separate thread
    virtual int join(pthread_t t);   // Connection thread
    virtual int exit();              // Thread to exit
    virtual int cancel(pthread_t t); // Cancel the thread
    virtual int destroy();           // Destruction of the thread

private:
    static void cleaner(void *pHandle); // Thread cleanup function
    static void *work(void *pHandle);   // Thread callback function

private:
    pthread_attr_t  t_attr;                         // Thread attributes
    pthread_t tid;                                  // The thread number
    const unsigned int max_pthread_size = 8 * 1024; // Thread stack size
};

#endif

2.线程基类的使用

#include "threadbase.h"

class MyTask: public ThreadBase
{
public:
    MyTask();
    ~MyTask();

    void routine();

protected:
};

#endif 
#include "mytask.h"

MyTask::MyTask()
{
    cjdebug("MyTask is new\n");
}

MyTask::~MyTask()
{
    ...
}

void MyTask::routine()
{
    cjdebug("Comm is running\n");

    while(true)
    {
       ...
    }
}

3. 使用标准 std::thread

以下代码展示std::thread是如何使用的

MyThread的类,并在类中组合了一个std::thread对象来实现

#include 
#include 

class MyThread 
{
public:
    MyThread() : thread_() {}
    ~MyThread() 
    {
        if (thread_.joinable()) 
        {
            thread_.join();
        }
    }

    void Start() 
    {
        // 启动线程
        thread_ = std::thread(&MyThread::Run, this);
    }

    void Join() 
    {
        // 等待线程执行完毕
        if (thread_.joinable()) 
        {
            thread_.join();
        }
    }

private:
    void Run() 
    {
        // 线程操作
        std::cout << "Thread function" << std::endl;
    }

    std::thread thread_;
};

int main()
{
    std::cout << "Main thread" << std::endl;

    MyThread myThread;
    myThread.Start();

    // 主线程继续执行其他操作

    myThread.Join();

    return 0;
}

你可能感兴趣的:(C/C++,设计师,c++)