设为首页 加入收藏

TOP

深入V8引擎-默认Platform之mac篇(2)(二)
2019-09-17 19:10:12 】 浏览:91
Tags:深入 引擎 默认 Platform mac篇
) {}
// ... }; // Create new thread. explicit Thread(const Options& options); // ... }

  可以简单理解这里给线程取了一个名字,在给Options命名的同时,其实也给Thread命名了,如下。

Thread::Thread(const Options& options)
    : data_(new PlatformData),
      stack_size_(options.stack_size()),
      start_semaphore_(nullptr) {
  if (stack_size_ > 0 && static_cast<size_t>(stack_size_) < PTHREAD_STACK_MIN) {
    stack_size_ = PTHREAD_STACK_MIN;
  }
  set_name(options.name());
}

class Thread {
  // The thread name length is limited to 16 based on Linux's implementation of
  // prctl().
  static const int kMaxThreadNameLength = 16;
  char name_[kMaxThreadNameLength];
}

void Thread::set_name(const char* name) {
  // 这里的长度被限制在16以内
  strncpy(name_, name, sizeof(name_));
  name_[sizeof(name_) - 1] = '\0';
}

  看注释说,由于Linux的prctl方法限制了长度,所以这里的name也最多只能保存16位,而且C++的字符串的最后一位还要留给结束符,所以理论上传入Options的超长字符串"V8 DefaultWorkerThreadsTaskRunner WorkerThread"只有前15位作为Thread的name保存下来了,也就是"V8 Defaultworke",非常戏剧性的把r给砍掉了。。。

  初始化完成后,会调用Start方法启动线程,这个方法并不需要子类实现,而是基类已经定义好了,保留关键代码如下。

// 3-4
void Thread::Start() {
  int result;
  // 线程对象
  pthread_attr_t attr;
  memset(&attr, 0, sizeof(attr));
  // 初始化线程对象
  result = pthread_attr_init(&attr);
  size_t stack_size = stack_size_;
  if (stack_size == 0) {
    stack_size = 1 * 1024 * 1024;
  }
  if (stack_size > 0) {
    // 设置线程对象属性
    result = pthread_attr_setstacksize(&attr, stack_size);
  }
  {
    // 创建一个新线程
    // 3-5
    result = pthread_create(&data_->thread_, &attr, ThreadEntry, this);
  }
  // 摧毁线程对象
  result = pthread_attr_destroy(&attr);
}

  参照一下文章开始的demo,可以看出去掉了合法性检测和宏之后,在初始化和启动线程基本上V8的形式是一样的。

  简单总结一下,V8初始化了一个DefaultPlatform类,计算了一下可用线程池大小,生成了几条线程弄进线程池,而每条线程的任务就是那个ThreadEntry,这篇全部写完算了。

 

  这个方法贼麻烦。

// 3-5
static void* ThreadEntry(void* arg) {
  Thread* thread = reinterpret_cast<Thread*>(arg);
  // We take the lock here to make sure that pthread_create finished first since
  // we don't know which thread will run first (the original thread or the new
  // one).
  { MutexGuard lock_guard(&thread->data()->thread_creation_mutex_); }
  // 3-6
  SetThreadName(thread->name());
  // 3-7
  thread->NotifyStartedAndRun();
  return nullptr;
}

  由于线程任务的参数定义与返回值都是void*,这里直接做一个强转。随后会加一个线程锁,因为这几个线程在初始化的时候并不需要同时执行这个任务。执行的第一个方法虽然从名字来看只是简单的给线程设置名字,但是内容却不简单。  

  传入SetThreadName方法的参数是之前那个被截断的字符串,看一下这个方法。

// 3-6
static void SetThreadName(const char* name) {
  // pthread_setname_np is only available in 10.6 or later, so test
  // for it at runtime.
  int (*dynamic_pthread_setname_np)(const char*);
  // 读取动态链接库
  *reinterpret_cast<void**>(&dynamic_pthread_setname_np) =
    dlsym(RTLD_DEFAULT, "pthread_setname_np");
  if (dynamic_pthread_setname_np == nullptr) return;

  // Mac OS X does not expose the length limit of the name, so hardcode it.
  static const int kMaxNameLength = 63;
  // 从读取到的方法处理name
  dynamic_pthread_setname_np(name);
}

  里面用了一个很玄的api的叫dlsym,官方解释如下。

The function dlsym() takes a "handle" of a dynamic library returned by dlopen() and the null-terminated symbol name, returning the address where that symbol is loaded into memory.

  大概就是根据句柄读取一个动态链接库,名字就是那个字符串,返回其在内存中的地址,所以这块的调试全是机器码,根本看不懂,最后返回的一个函数。

  知道这是个函数就行了,至于怎

首页 上一页 1 2 3 下一页 尾页 2/3/3
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
上一篇VUE中全局变量的定义和使用 下一篇JavaScript Timing 事件及两种时..

最新文章

热门文章

Hot 文章

Python

C 语言

C++基础

大数据基础

linux编程基础

C/C++面试题目