default-platform.cc 5.39 KB
Newer Older
1
// Copyright 2013 the V8 project authors. All rights reserved.
2 3
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
4

5
#include "src/libplatform/default-platform.h"
6

7
#include <algorithm>
8 9
#include <queue>

10 11
#include "src/base/logging.h"
#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 21 22 23 24 25 26 27
v8::Platform* CreateDefaultPlatform(int thread_pool_size) {
  DefaultPlatform* platform = new DefaultPlatform();
  platform->SetThreadPoolSize(thread_pool_size);
  platform->EnsureInitialized();
  return platform;
}


28 29 30 31
bool PumpMessageLoop(v8::Platform* platform, v8::Isolate* isolate) {
  return reinterpret_cast<DefaultPlatform*>(platform)->PumpMessageLoop(isolate);
}

32
const int DefaultPlatform::kMaxThreadPoolSize = 8;
33

34
DefaultPlatform::DefaultPlatform()
35
    : initialized_(false), thread_pool_size_(0) {}
36 37 38


DefaultPlatform::~DefaultPlatform() {
39
  base::LockGuard<base::Mutex> guard(&lock_);
40
  queue_.Terminate();
41
  if (initialized_) {
42
    for (auto i = thread_pool_.begin(); i != thread_pool_.end(); ++i) {
43 44 45
      delete *i;
    }
  }
46 47
  for (auto i = main_thread_queue_.begin(); i != main_thread_queue_.end();
       ++i) {
48 49 50 51 52
    while (!i->second.empty()) {
      delete i->second.front();
      i->second.pop();
    }
  }
53 54 55 56 57 58 59
  for (auto i = main_thread_delayed_queue_.begin();
       i != main_thread_delayed_queue_.end(); ++i) {
    while (!i->second.empty()) {
      delete i->second.top().second;
      i->second.pop();
    }
  }
60 61
}

62

63
void DefaultPlatform::SetThreadPoolSize(int thread_pool_size) {
64
  base::LockGuard<base::Mutex> guard(&lock_);
65
  DCHECK(thread_pool_size >= 0);
66
  if (thread_pool_size < 1) {
67
    thread_pool_size = base::SysInfo::NumberOfProcessors() - 1;
68
  }
69 70
  thread_pool_size_ =
      std::max(std::min(thread_pool_size, kMaxThreadPoolSize), 1);
71
}
72

73 74

void DefaultPlatform::EnsureInitialized() {
75
  base::LockGuard<base::Mutex> guard(&lock_);
76 77 78 79
  if (initialized_) return;
  initialized_ = true;

  for (int i = 0; i < thread_pool_size_; ++i)
80 81
    thread_pool_.push_back(new WorkerThread(&queue_));
}
82

83

84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109
Task* DefaultPlatform::PopTaskInMainThreadQueue(v8::Isolate* isolate) {
  auto it = main_thread_queue_.find(isolate);
  if (it == main_thread_queue_.end() || it->second.empty()) {
    return NULL;
  }
  Task* task = it->second.front();
  it->second.pop();
  return task;
}


Task* DefaultPlatform::PopTaskInMainThreadDelayedQueue(v8::Isolate* isolate) {
  auto it = main_thread_delayed_queue_.find(isolate);
  if (it == main_thread_delayed_queue_.end() || it->second.empty()) {
    return NULL;
  }
  double now = MonotonicallyIncreasingTime();
  std::pair<double, Task*> deadline_and_task = it->second.top();
  if (deadline_and_task.first > now) {
    return NULL;
  }
  it->second.pop();
  return deadline_and_task.second;
}


110 111 112 113
bool DefaultPlatform::PumpMessageLoop(v8::Isolate* isolate) {
  Task* task = NULL;
  {
    base::LockGuard<base::Mutex> guard(&lock_);
114 115 116 117 118 119 120 121 122 123 124

    // Move delayed tasks that hit their deadline to the main queue.
    task = PopTaskInMainThreadDelayedQueue(isolate);
    while (task != NULL) {
      main_thread_queue_[isolate].push(task);
      task = PopTaskInMainThreadDelayedQueue(isolate);
    }

    task = PopTaskInMainThreadQueue(isolate);

    if (task == NULL) {
125 126 127 128 129 130 131 132
      return false;
    }
  }
  task->Run();
  delete task;
  return true;
}

133

134 135
void DefaultPlatform::CallOnBackgroundThread(Task *task,
                                             ExpectedRuntime expected_runtime) {
136
  EnsureInitialized();
137
  queue_.Append(task);
138 139 140 141
}


void DefaultPlatform::CallOnForegroundThread(v8::Isolate* isolate, Task* task) {
142 143
  base::LockGuard<base::Mutex> guard(&lock_);
  main_thread_queue_[isolate].push(task);
144 145
}

146

147 148 149
void DefaultPlatform::CallDelayedOnForegroundThread(Isolate* isolate,
                                                    Task* task,
                                                    double delay_in_seconds) {
150
  base::LockGuard<base::Mutex> guard(&lock_);
151 152 153 154 155
  double deadline = MonotonicallyIncreasingTime() + delay_in_seconds;
  main_thread_delayed_queue_[isolate].push(std::make_pair(deadline, task));
}


156 157 158 159 160 161 162 163 164
void DefaultPlatform::CallIdleOnForegroundThread(Isolate* isolate,
                                                 IdleTask* task) {
  UNREACHABLE();
}


bool DefaultPlatform::IdleTasksEnabled(Isolate* isolate) { return false; }


165 166 167 168
double DefaultPlatform::MonotonicallyIncreasingTime() {
  return base::TimeTicks::HighResolutionNow().ToInternalValue() /
         static_cast<double>(base::Time::kMicrosecondsPerSecond);
}
169 170


171 172 173 174 175 176 177 178 179
uint64_t DefaultPlatform::AddTraceEvent(
    char phase, const uint8_t* category_enabled_flag, const char* name,
    const char* scope, uint64_t id, uint64_t bind_id, int num_args,
    const char** arg_names, const uint8_t* arg_types,
    const uint64_t* arg_values, unsigned int flags) {
  return 0;
}


180 181 182 183 184 185 186 187 188 189 190 191 192 193 194
void DefaultPlatform::UpdateTraceEventDuration(
    const uint8_t* category_enabled_flag, const char* name, uint64_t handle) {}


const uint8_t* DefaultPlatform::GetCategoryGroupEnabled(const char* name) {
  static uint8_t no = 0;
  return &no;
}


const char* DefaultPlatform::GetCategoryGroupName(
    const uint8_t* category_enabled_flag) {
  static const char dummy[] = "dummy";
  return dummy;
}
195

196

197 198 199 200
size_t DefaultPlatform::NumberOfAvailableBackgroundThreads() {
  return static_cast<size_t>(thread_pool_size_);
}

201 202
}  // namespace platform
}  // namespace v8