CAFFE源码学习笔记之五-internal_thread

一、前言
该类实际是boost::thread的包裹器。boost十分强大,可以不用修改就在linux和windows使用,避免了使用内核函数的移植性问题。

二、源码分析
类的构造函数就默认初始化boost::thread,析构函数直接调用线程停止函数。
成员函数包括开始线程,结束线程,判断线程是否开始,要求线程结束

class InternalThread {
 public:
  InternalThread() : thread_() {}
  virtual ~InternalThread();

  void StartInternalThread();


  void StopInternalThread();

  bool is_started() const;

 protected:
  /* Implement this method in your subclass
      with the code you want your thread to run. */
  virtual void InternalThreadEntry() {}

  /* Should be tested when running loops to exit when requested. */
  bool must_stop();

 private:
  void entry(int device, Caffe::Brew mode, int rand_seed,
      int solver_count, int solver_rank, bool multiprocess);

  shared_ptr<boost::thread> thread_;
};

}  // namespace caffe

具体实现:
如何开始线程?
首先,要将全局的资源搬运过来;
然后,用搬运过来的原始的全局资源初始化本线程的全局资源???
最后,初始化boost::thread。

void InternalThread::StartInternalThread() {
  CHECK(!is_started()) << "Threads should persist and not be restarted.";

  int device = 0;
#ifndef CPU_ONLY
  CUDA_CHECK(cudaGetDevice(&device));
#endif
  Caffe::Brew mode = Caffe::mode();
  int rand_seed = caffe_rng_rand();
  int solver_count = Caffe::solver_count();
  int solver_rank = Caffe::solver_rank();
  bool multiprocess = Caffe::multiprocess();

  try {
    thread_.reset(new boost::thread(&InternalThread::entry, this, device, mode,
          rand_seed, solver_count, solver_rank, multiprocess));//这里用函数指针加绑定参数的形式构造了thread
  } catch (std::exception& e) {
    LOG(FATAL) << "Thread exception: " << e.what();
  }
}

其中entry函数就是用其他线程的全局资源初始化本线程的:

void InternalThread::entry(int device, Caffe::Brew mode, int rand_seed,
    int solver_count, int solver_rank, bool multiprocess) {
#ifndef CPU_ONLY
  CUDA_CHECK(cudaSetDevice(device));
#endif
  Caffe::set_mode(mode);
  Caffe::set_random_seed(rand_seed);
  Caffe::set_solver_count(solver_count);
  Caffe::set_solver_rank(solver_rank);
  Caffe::set_multiprocess(multiprocess);

  InternalThreadEntry();
}

如何判断线程开始了?
线程存在且是可以等待执行的:

bool InternalThread::is_started() const {
  return thread_ && thread_->joinable();

如何结束线程?
要想主动终结一个线程是很费劲的,caffe也没有做这种费力不讨好的事情,而是被动的等待。
caffe采取是设置must_stop()函数自动检测终结条件的退出方式。
thread里的thread_->interruption_requested()提供中断检测。

bool InternalThread::must_stop() {
  return thread_ && thread_->interruption_requested();
}

同时,caffe提供了从外部主动触发interrupt操作,然后为了使可能处于阻塞状态的线程苏醒,使用join()唤醒之。

void InternalThread::StopInternalThread() {
  if (is_started()) {
    thread_->interrupt();
    try {
      thread_->join();
    } catch (boost::thread_interrupted&) {
    } catch (std::exception& e) {
      LOG(FATAL) << "Thread exception: " << e.what();
    }
  }
}

三、总结
该类掌控了线程的生命周期,是多线程系统的基石。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值