设为首页 加入收藏

TOP

深入V8引擎-默认Platform之mac篇(2)(一)
2019-09-17 19:10:12 】 浏览:87
Tags:深入 引擎 默认 Platform mac篇

  先说结论,V8引擎在默认Platform中初始化的这个线程是用于处理类似于setTimeout的延时任务。

  另外附一些图,包括继承树、关键属性归属、纯逻辑工作流程,对代码木得兴趣的看完图可以X掉了。

  上一篇讲了V8初始化默认Platform对象时会做三件事,其中生成空白DefaultPlatform、获取线程池大小已经讲过了,剩下线程启动相关的内容。

  写之前花了10几分钟学了下mac下C++的线程,对API有一个初步了解,给一个简单的例子,大概流程如下。

// V8源码中设置的stack_size 在测试demo中不好使
const int stack_size = 1 * 1024 * 512;
int tmp = 0;

// 线程的任务 参数来源于创建时的第四个参数
void* add(void* number){
  tmp = tmp + *(int*)number;
  printf("tmp: %i\n", tmp);
  return nullptr;
};

int main(int argc, const char * argv[]) {
  // 创建线程对象
  pthread_t pt;
  // 创建线程属性
  pthread_attr_t attr;
  memset(&attr, 0, sizeof(attr));
  pthread_attr_init(&attr);
  // 设置属性的size
  pthread_attr_setstacksize(&attr, stack_size);
  // 函数参数
  int num = 5;
  int* ptr = #
  // 生成一个线程
  // 参数列表参照各个变量
  int ret = pthread_create(&pt, &attr, add, ptr);
  if(ret != 0) printf("cannot create thread");
  return 0;
}

  通过几个步骤,就可以创建一条线程来处理任务,启动后的输出就懒得截图了,反正就是打印一个5。

  有了上面的例子,可以慢慢来看V8初始化时多线程的启动过程,首先是入门方法。

// 3
void DefaultPlatform::EnsureBackgroundTaskRunnerInitialized() {
  // 这里初始化DefaultPlatform的属性 需要加锁
  base::MutexGuard guard(&lock_);
  if (!worker_threads_task_runner_) {
    worker_threads_task_runner_ =
        // 3-2
        std::make_shared<DefaultWorkerThreadsTaskRunner>(
            thread_pool_size_, time_function_for_testing_
                                   ? time_function_for_testing_
                                  // 3-1
                                   : DefaultTimeFunction);
  }
}

// 3-1
double DefaultTimeFunction() {
  return base::TimeTicks::HighResolutionNow().ToInternalValue() /
         static_cast<double>(base::Time::kMicrosecondsPerSecond);
}

  if中的worker_threads_task_runner是DefaultPlatform的私有属性,由于初始化时默认值为NULL,这里做一个定义赋值。第一个参数是在第二步获取的线程池大小,第二个参数是一个计数方法,默认引用之前Time模块里的东西,返回硬件时间戳,具体实现可以看我之前写的。

  接下来看DefaultWorkerThreadsTaskRunner类的构造函数,接受2个参数。

// 3-2
// queue_ => DelayedTaskQueue::DelayedTaskQueue(TimeFunction time_function) : time_function_(time_function) {}
DefaultWorkerThreadsTaskRunner::DefaultWorkerThreadsTaskRunner(
    uint32_t thread_pool_size, TimeFunction time_function)
    : queue_(time_function),
      time_function_(time_function),
      thread_pool_size_(thread_pool_size) {
  for (uint32_t i = 0; i < thread_pool_size; ++i) {
    // 3-3
    thread_pool_.push_back(base::make_unique<WorkerThread>(this));
  }
}

  用2个参数初始化了3个属性,并且根据size往线程池中添加线程,thread_pool_这个属性用vector在管理,push_back相当于JS的push,当成数组来理解就行了。

  添加的WorkerThread类是在DefaultWorkerThreadsTaskRunner里面的一个私有内部类,继承于Thread,单纯的用来管理线程。C++的this比较简单,没有JS那么多概念,就是一个指向当前对象的指针,来看一下线程类的构造函数。

// 3-3
DefaultWorkerThreadsTaskRunner::WorkerThread::WorkerThread(DefaultWorkerThreadsTaskRunner* runner)
    // 这里调用父类构造函数
    : Thread(Options("V8 DefaultWorkerThreadsTaskRunner WorkerThread")),
    // 这里初始化当前类属性
      runner_(runner) {
  // 3-4
  Start();
}

  这里同时调用了父类构造函数并初始化本身的属性,runner就是上面那个对象本身。这个构造函数长得比较奇怪,其中Options类是Thread的内部类,有一个接受一个类型为字符串的构造函数,而Thread的构造函数只接受Options类型,所以会这样,代码如下。

class Thread {
 public:
  // Opaque data type for thread-local storage keys.
  using LocalStorageKey = int32_t;

  class Options {
   public:
    Options() : name_("v8:<unknown>"), stack_size_(0) {}
    explicit Options(const char* name, int stack_size = 0)
        : name_(name), stack_size_(stack_size
首页 上一页 1 2 3 下一页 尾页 1/3/3
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
上一篇VUE中全局变量的定义和使用 下一篇JavaScript Timing 事件及两种时..

最新文章

热门文章

Hot 文章

Python

C 语言

C++基础

大数据基础

linux编程基础

C/C++面试题目