浅析muduo库中的线程设施02

接下来,聊一聊主题–Thread

/***Thread.h***/
class Thread : boost::noncopyable   //禁止拷贝
{
 public:
  typedef boost::function<void ()> ThreadFunc;//仿函数对象,利用回调的方式使用线程函数

  explicit Thread(const ThreadFunc&, const string& name = string());//普通的线程构造函数
#ifdef __GXX_EXPERIMENTAL_CXX0X__
  explicit Thread(ThreadFunc&&, const string& name = string());//移动的线程构造函数,比上面的更节省资源std::move
#endif
  ~Thread();//析构函数

  void start();//启动线程
  int join(); // 类似于 pthread_join()

  bool started() const { return started_; }
  // pthread_t pthreadId() const { return pthreadId_; }
  pid_t tid() const { return *tid_; } //返回线程索引
  const string& name() const { return name_; }//返回线程名字

  static int numCreated() { return numCreated_.get(); }

 private:
  void setDefaultName();

  bool       started_;  //是否启动
  bool       joined_;   //是否终止
  pthread_t  pthreadId_;    //线程索引
  boost::shared_ptr<pid_t> tid_;    //指向线程索引的智能指针
  ThreadFunc func_;     //线程主题函数
  string     name_;     //线程名字

  static AtomicInt32 numCreated_;   //static变量在所有的线程对象中共享,为由该类产生的线程排序
};
  • 在muduo的线程对象封装中,最精彩的是使用boost::function函数对象将线程函数以回调的方式传递进线程对象中。

typedef boost::function<void ()> ThreadFun;

  • 在多线程情况下,避免在对象外操作指向对象的指针的情形,可以在一定程度上保证了线程安全。
/***Thread.cc***/
//两种线程构造函数
Thread::Thread(const ThreadFunc& func, const string& n)
  : started_(false),
    joined_(false),
    pthreadId_(0),
    tid_(new pid_t(0)),
    func_(func),
    name_(n)
{
  setDefaultName();
}

#ifdef __GXX_EXPERIMENTAL_CXX0X__
Thread::Thread(ThreadFunc&& func, const string& n)
  : started_(false),
    joined_(false),
    pthreadId_(0),
    tid_(new pid_t(0)),
    func_(std::move(func)),
    name_(n)
{
  setDefaultName();     
}

#endif

Thread::~Thread() 
{
  if (started_ && !joined_)     //将该线程设置为分离属性
  {
    pthread_detach(pthreadId_);     //线程结束将自动回收资源
  }
}

void Thread::setDefaultName()   //设置线程名字,比如Thread1,Thread2等
{
  int num = numCreated_.incrementAndGet();
  if (name_.empty())
  {
    char buf[32];   
    snprintf(buf, sizeof buf, "Thread%d", num);
    name_ = buf;
  }
}

void Thread::start()
{
  assert(!started_);    //断言线程是否已经开始运行
  started_ = true;      //断言失败则设置线程开始运行的标志
  // FIXME: move(func_)
  detail::ThreadData* data = new detail::ThreadData(func_, name_, tid_);   //获得线程运行的所需要的参数
  if (pthread_create(&pthreadId_, NULL, &detail::startThread, data))
  {     //开始线程
    started_ = false;
    printf("blockDim.x: %d\n",blockDim.x);
    delete data; // or no delete?
    LOG_SYSFATAL << "Failed in pthread_create";
  }
}

int Thread::join()
{
  assert(started_);     //断言线程是否正在运行
  assert(!joined_);     //断言线程是否已经被终止
  joined_ = true;
  return pthread_join(pthreadId_, NULL);        //等待线程结束
}
  • 在线程的析构函数中只设置线程的分离属性,即等待线程运行结束后自动回收线程资源,不强行终止线程。
struct ThreadData //thread的再封装
{
  typedef muduo::Thread::ThreadFunc ThreadFunc;
  ThreadFunc func_;
  string name_;
  boost::weak_ptr<pid_t> wkTid_;

  ThreadData(const ThreadFunc& func,
             const string& name,
             const boost::shared_ptr<pid_t>& tid)
    : func_(func),
      name_(name),
      wkTid_(tid)
  { }

  void runInThread()//真正让线程跑起来的函数
  {
    pid_t tid = muduo::CurrentThread::tid();

    boost::shared_ptr<pid_t> ptid = wkTid_.lock();
    if (ptid)
    {
      *ptid = tid;
      ptid.reset();
    }

    muduo::CurrentThread::t_threadName = name_.empty() ? "muduoThread" : name_.c_str();
    ::prctl(PR_SET_NAME, muduo::CurrentThread::t_threadName);
    try //异常捕捉部分
    {
      func_();  //线程起跑
      muduo::CurrentThread::t_threadName = "finished";
    }
    catch (const Exception& ex)
    {
      muduo::CurrentThread::t_threadName = "crashed";
      fprintf(stderr, "exception caught in Thread %s\n", name_.c_str());
      fprintf(stderr, "reason: %s\n", ex.what());
      fprintf(stderr, "stack trace: %s\n", ex.stackTrace());
      abort();
    }
    catch (const std::exception& ex)
    {
      muduo::CurrentThread::t_threadName = "crashed";
      fprintf(stderr, "exception caught in Thread %s\n", name_.c_str());
      fprintf(stderr, "reason: %s\n", ex.what());
      abort();
    }
    catch (...)
    {
      muduo::CurrentThread::t_threadName = "crashed";
      fprintf(stderr, "unknown exception caught in Thread %s\n", name_.c_str());
      throw; // rethrow
    }
  }
};

void* startThread(void* obj)    //由pthread_create调用的函数
{
  ThreadData* data = static_cast<ThreadData*>(obj);
  data->runInThread();
  delete data;
  return NULL;
}
  • 将线程中的若干数据保存到ThreadData中,然后将ThreadData作为传递给pthread_create(...,void* arg)中的最后一个数据参数传递给void Thread(void* )标准的线程启动函数。然后在标准的线程启动函数内将void* arg强行转化为ThreadData,然后使用ThreadData中的runInThread函数启动线程。

  • 在使用muduo的线程接口时,使用bind将线程运行函数再打包,然后传递进Thread.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值