Linux组件封装 使用面向对象编程封装Thread

本文介绍了一种基于POSIX线程API的自定义Thread类封装方法,重点讲解了如何利用pthread_create函数创建线程,并通过静态成员函数实现线程运行逻辑的传递。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

C++11提供了thread,但是过于复杂,我们还是倾向于在项目中编写自己的Thread。

Posix Thread的使用这里不再赘述。

重点是这个函数:

#include <pthread.h>
int pthread_create(pthread_t *thread, const pthread_attr_t *attr,
                          void *(*start_routine) (void *), void *arg);

第三个参数是一个回调函数,该函数必须返回值为void*,而且只有一个参数,类型也是void*。

POSIX的thread默认是joinable,需要手工调用pthread_join函数来回收,也可以调用pthread_detach将其变为detachable,此时不需要手工回收线程。

下面介绍Thread的封装。

我们把Thread的声明先放在这里:

#ifndef THREAD_H_
#define THREAD_H_

#include "NonCopyable.h"
#include <pthread.h>

class Thread : NonCopyable
{
public:
    Thread();
    virtual ~Thread();

    void start();
    void join();

    virtual void run() = 0;

    pthread_t getThreadId() const
    { return threadId_; }

private:

      //提供给pthread_create的第三个参数使用
    static void *runInThread(void *arg);
    
    pthread_t threadId_;
    //pid_t tid_; //进程标示
    bool isRunning_;
};

#endif //THREAD_H_

这里需要说明的是:

1.首先,为了获得最干净的语义,Thread应该是不可复制的,所以需要继承NonCopyable。

2.其次,为了调用pthread_create创建线程,我们往里面注册的不能是一个成员函数,因为成员函数含有一个隐式参数,导致函数的指针类型并不是void *(*start_routine) (void *),所以我们采用了static函数

3.static函数无法访问某一对象的成员,所以我们在调用pthread_create时,将this指针作为回调函数的参数

NonCopyable类的定义如下:

#ifndef NONCOPYABLE_H
#define NONCOPYABLE_H


class NonCopyable //禁用值语义
{
public:
    NonCopyable() { }
    ~NonCopyable() { }
private:
    NonCopyable(const NonCopyable &);
    void operator=(const NonCopyable &);
};


#endif //NONCOPYABLE_H

这里相关代码如下:

//static
void *Thread::runInThread(void *arg)
{
    Thread *pt = static_cast<Thread*>(arg);
    //pt->tid_ = syscall(SYS_gettid);
    pt->run();
    return NULL;
}

用户将自己的逻辑注册在run中就可以了。

这个Thread不提供detach函数,因为我们在析构函数中做了如下的处理,如果Thread对象析构,线程还在运行,那么需要将Thread设置为detach状态

Thread::~Thread()
{
    if(isRunning_)
    {
        pthread_detach(threadId_);
    }
}


完整的CPP实现如下:

#include "Thread.h"
#include <assert.h>
#include <unistd.h>
#include "MutexLock.h" //TINY_CHECK

Thread::Thread()
    :threadId_(0),
     isRunning_(false)
{

}

Thread::~Thread()
{
    if(isRunning_)
    {
        TINY_CHECK(!pthread_detach(threadId_));
    }
}

//static
void *Thread::runInThread(void *arg)
{
    Thread *pt = static_cast<Thread*>(arg);
    //pt->tid_ = syscall(SYS_gettid);
    pt->run();
    return NULL;
}

void Thread::start()
{
    TINY_CHECK(!pthread_create(&threadId_, NULL, Thread::runInThread, this));
    isRunning_ = true;
}

void Thread::join()
{
    assert(isRunning_);
    TINY_CHECK(!pthread_join(threadId_, NULL));
    isRunning_ = false;
}


以下为文章的出处! !
点这里打开原文
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值