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/sys-info.h"
13#include "src/libplatform/worker-thread.h"
14
15namespace v8 {
16namespace platform {
17
18
19v8::Platform* CreateDefaultPlatform(int thread_pool_size) {
20  DefaultPlatform* platform = new DefaultPlatform();
21  platform->SetThreadPoolSize(thread_pool_size);
22  platform->EnsureInitialized();
23  return platform;
24}
25
26
27bool PumpMessageLoop(v8::Platform* platform, v8::Isolate* isolate) {
28  return reinterpret_cast<DefaultPlatform*>(platform)->PumpMessageLoop(isolate);
29}
30
31
32const int DefaultPlatform::kMaxThreadPoolSize = 4;
33
34
35DefaultPlatform::DefaultPlatform()
36    : initialized_(false), thread_pool_size_(0) {}
37
38
39DefaultPlatform::~DefaultPlatform() {
40  base::LockGuard<base::Mutex> guard(&lock_);
41  queue_.Terminate();
42  if (initialized_) {
43    for (std::vector<WorkerThread*>::iterator i = thread_pool_.begin();
44         i != thread_pool_.end(); ++i) {
45      delete *i;
46    }
47  }
48  for (std::map<v8::Isolate*, std::queue<Task*> >::iterator i =
49           main_thread_queue_.begin();
50       i != main_thread_queue_.end(); ++i) {
51    while (!i->second.empty()) {
52      delete i->second.front();
53      i->second.pop();
54    }
55  }
56}
57
58
59void DefaultPlatform::SetThreadPoolSize(int thread_pool_size) {
60  base::LockGuard<base::Mutex> guard(&lock_);
61  DCHECK(thread_pool_size >= 0);
62  if (thread_pool_size < 1) {
63    thread_pool_size = base::SysInfo::NumberOfProcessors();
64  }
65  thread_pool_size_ =
66      std::max(std::min(thread_pool_size, kMaxThreadPoolSize), 1);
67}
68
69
70void DefaultPlatform::EnsureInitialized() {
71  base::LockGuard<base::Mutex> guard(&lock_);
72  if (initialized_) return;
73  initialized_ = true;
74
75  for (int i = 0; i < thread_pool_size_; ++i)
76    thread_pool_.push_back(new WorkerThread(&queue_));
77}
78
79
80bool DefaultPlatform::PumpMessageLoop(v8::Isolate* isolate) {
81  Task* task = NULL;
82  {
83    base::LockGuard<base::Mutex> guard(&lock_);
84    std::map<v8::Isolate*, std::queue<Task*> >::iterator it =
85        main_thread_queue_.find(isolate);
86    if (it == main_thread_queue_.end() || it->second.empty()) {
87      return false;
88    }
89    task = it->second.front();
90    it->second.pop();
91  }
92  task->Run();
93  delete task;
94  return true;
95}
96
97void DefaultPlatform::CallOnBackgroundThread(Task *task,
98                                             ExpectedRuntime expected_runtime) {
99  EnsureInitialized();
100  queue_.Append(task);
101}
102
103
104void DefaultPlatform::CallOnForegroundThread(v8::Isolate* isolate, Task* task) {
105  base::LockGuard<base::Mutex> guard(&lock_);
106  main_thread_queue_[isolate].push(task);
107}
108
109} }  // namespace v8::platform
110