Home | History | Annotate | Download | only in libplatform
      1 // Copyright 2013 the V8 project authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #include "src/libplatform/default-platform.h"
      6 
      7 #include <algorithm>
      8 #include <queue>
      9 
     10 #include "src/base/logging.h"
     11 #include "src/base/platform/platform.h"
     12 #include "src/base/platform/time.h"
     13 #include "src/base/sys-info.h"
     14 #include "src/libplatform/worker-thread.h"
     15 
     16 namespace v8 {
     17 namespace platform {
     18 
     19 
     20 v8::Platform* CreateDefaultPlatform(int thread_pool_size) {
     21   DefaultPlatform* platform = new DefaultPlatform();
     22   platform->SetThreadPoolSize(thread_pool_size);
     23   platform->EnsureInitialized();
     24   return platform;
     25 }
     26 
     27 
     28 bool PumpMessageLoop(v8::Platform* platform, v8::Isolate* isolate) {
     29   return reinterpret_cast<DefaultPlatform*>(platform)->PumpMessageLoop(isolate);
     30 }
     31 
     32 
     33 const int DefaultPlatform::kMaxThreadPoolSize = 4;
     34 
     35 
     36 DefaultPlatform::DefaultPlatform()
     37     : initialized_(false), thread_pool_size_(0) {}
     38 
     39 
     40 DefaultPlatform::~DefaultPlatform() {
     41   base::LockGuard<base::Mutex> guard(&lock_);
     42   queue_.Terminate();
     43   if (initialized_) {
     44     for (auto i = thread_pool_.begin(); i != thread_pool_.end(); ++i) {
     45       delete *i;
     46     }
     47   }
     48   for (auto i = main_thread_queue_.begin(); i != main_thread_queue_.end();
     49        ++i) {
     50     while (!i->second.empty()) {
     51       delete i->second.front();
     52       i->second.pop();
     53     }
     54   }
     55   for (auto i = main_thread_delayed_queue_.begin();
     56        i != main_thread_delayed_queue_.end(); ++i) {
     57     while (!i->second.empty()) {
     58       delete i->second.top().second;
     59       i->second.pop();
     60     }
     61   }
     62 }
     63 
     64 
     65 void DefaultPlatform::SetThreadPoolSize(int thread_pool_size) {
     66   base::LockGuard<base::Mutex> guard(&lock_);
     67   DCHECK(thread_pool_size >= 0);
     68   if (thread_pool_size < 1) {
     69     thread_pool_size = base::SysInfo::NumberOfProcessors();
     70   }
     71   thread_pool_size_ =
     72       std::max(std::min(thread_pool_size, kMaxThreadPoolSize), 1);
     73 }
     74 
     75 
     76 void DefaultPlatform::EnsureInitialized() {
     77   base::LockGuard<base::Mutex> guard(&lock_);
     78   if (initialized_) return;
     79   initialized_ = true;
     80 
     81   for (int i = 0; i < thread_pool_size_; ++i)
     82     thread_pool_.push_back(new WorkerThread(&queue_));
     83 }
     84 
     85 
     86 Task* DefaultPlatform::PopTaskInMainThreadQueue(v8::Isolate* isolate) {
     87   auto it = main_thread_queue_.find(isolate);
     88   if (it == main_thread_queue_.end() || it->second.empty()) {
     89     return NULL;
     90   }
     91   Task* task = it->second.front();
     92   it->second.pop();
     93   return task;
     94 }
     95 
     96 
     97 Task* DefaultPlatform::PopTaskInMainThreadDelayedQueue(v8::Isolate* isolate) {
     98   auto it = main_thread_delayed_queue_.find(isolate);
     99   if (it == main_thread_delayed_queue_.end() || it->second.empty()) {
    100     return NULL;
    101   }
    102   double now = MonotonicallyIncreasingTime();
    103   std::pair<double, Task*> deadline_and_task = it->second.top();
    104   if (deadline_and_task.first > now) {
    105     return NULL;
    106   }
    107   it->second.pop();
    108   return deadline_and_task.second;
    109 }
    110 
    111 
    112 bool DefaultPlatform::PumpMessageLoop(v8::Isolate* isolate) {
    113   Task* task = NULL;
    114   {
    115     base::LockGuard<base::Mutex> guard(&lock_);
    116 
    117     // Move delayed tasks that hit their deadline to the main queue.
    118     task = PopTaskInMainThreadDelayedQueue(isolate);
    119     while (task != NULL) {
    120       main_thread_queue_[isolate].push(task);
    121       task = PopTaskInMainThreadDelayedQueue(isolate);
    122     }
    123 
    124     task = PopTaskInMainThreadQueue(isolate);
    125 
    126     if (task == NULL) {
    127       return false;
    128     }
    129   }
    130   task->Run();
    131   delete task;
    132   return true;
    133 }
    134 
    135 
    136 void DefaultPlatform::CallOnBackgroundThread(Task *task,
    137                                              ExpectedRuntime expected_runtime) {
    138   EnsureInitialized();
    139   queue_.Append(task);
    140 }
    141 
    142 
    143 void DefaultPlatform::CallOnForegroundThread(v8::Isolate* isolate, Task* task) {
    144   base::LockGuard<base::Mutex> guard(&lock_);
    145   main_thread_queue_[isolate].push(task);
    146 }
    147 
    148 
    149 void DefaultPlatform::CallDelayedOnForegroundThread(Isolate* isolate,
    150                                                     Task* task,
    151                                                     double delay_in_seconds) {
    152   base::LockGuard<base::Mutex> guard(&lock_);
    153   double deadline = MonotonicallyIncreasingTime() + delay_in_seconds;
    154   main_thread_delayed_queue_[isolate].push(std::make_pair(deadline, task));
    155 }
    156 
    157 
    158 void DefaultPlatform::CallIdleOnForegroundThread(Isolate* isolate,
    159                                                  IdleTask* task) {
    160   UNREACHABLE();
    161 }
    162 
    163 
    164 bool DefaultPlatform::IdleTasksEnabled(Isolate* isolate) { return false; }
    165 
    166 
    167 double DefaultPlatform::MonotonicallyIncreasingTime() {
    168   return base::TimeTicks::HighResolutionNow().ToInternalValue() /
    169          static_cast<double>(base::Time::kMicrosecondsPerSecond);
    170 }
    171 
    172 
    173 uint64_t DefaultPlatform::AddTraceEvent(
    174     char phase, const uint8_t* category_enabled_flag, const char* name,
    175     uint64_t id, uint64_t bind_id, int num_args, const char** arg_names,
    176     const uint8_t* arg_types, const uint64_t* arg_values, unsigned int flags) {
    177   return 0;
    178 }
    179 
    180 
    181 void DefaultPlatform::UpdateTraceEventDuration(
    182     const uint8_t* category_enabled_flag, const char* name, uint64_t handle) {}
    183 
    184 
    185 const uint8_t* DefaultPlatform::GetCategoryGroupEnabled(const char* name) {
    186   static uint8_t no = 0;
    187   return &no;
    188 }
    189 
    190 
    191 const char* DefaultPlatform::GetCategoryGroupName(
    192     const uint8_t* category_enabled_flag) {
    193   static const char dummy[] = "dummy";
    194   return dummy;
    195 }
    196 }  // namespace platform
    197 }  // namespace v8
    198