2 * Copyright (C) 2010 The Android Open Source Project
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
21 #include "js_support.h"
22 #include "node_object_wrap.h"
23 #include "node_util.h"
27 #include "worker_v8.h"
30 //#define WORKER_V8_V8_DEBUG
31 #ifdef WORKER_V8_V8_DEBUG
33 #define DBG(...) ALOGD(__VA_ARGS__)
41 v8::Persistent<v8::FunctionTemplate> WorkerV8Template;
43 class WorkerV8 : public ObjectWrap {
49 v8::Persistent<v8::Object> js_this;
50 v8::Persistent<v8::Value> value;
53 pthread_mutex_t ai_free_list_mutex_;
54 std::queue<ArgInfo *> ai_free_list_;
56 ArgInfo *ObtainArgInfo() {
58 pthread_mutex_lock(&ai_free_list_mutex_);
59 if (ai_free_list_.size() == 0) {
62 ai = ai_free_list_.front();
65 pthread_mutex_unlock(&ai_free_list_mutex_);
69 void ReleaseArgInfo(ArgInfo *ai) {
70 pthread_mutex_lock(&ai_free_list_mutex_);
71 ai_free_list_.push(ai);
72 pthread_mutex_unlock(&ai_free_list_mutex_);
75 class Handler : public WorkerQueue {
77 v8::Persistent<v8::Value> functionValue_;
81 Handler(WorkerV8 *worker, v8::Handle<v8::Value> value)
83 functionValue_ = v8::Persistent<v8::Value>::New(value);
86 void Process(void *param) {
87 DBG("Handler::Process: E");
90 v8::HandleScope handle_scope;
91 v8::TryCatch try_catch;
92 try_catch.SetVerbose(true);
94 ArgInfo *ai = (ArgInfo*)param;
95 v8::Handle<v8::Value> args(ai->value);
96 v8::Function::Cast(*functionValue_)->Call(ai->js_this, 1, &args);
98 ai->js_this.Dispose();
101 worker_->ReleaseArgInfo(ai);
103 DBG("Handler::Process: X");
110 WorkerV8(v8::Handle<v8::Object> self, v8::Handle<v8::Value> functionValue) {
111 DBG("WorkerV8::WorkerV8 E:");
112 pthread_mutex_init(&ai_free_list_mutex_, NULL);
113 handler_ = new Handler(this, functionValue);
115 DBG("WorkerV8::WorkerV8 X: this=%p handler_=%p", this, handler_);
118 virtual ~WorkerV8() {
119 DBG("~WorkerV8::WorkerV8 E:");
120 DBG("~WorkerV8::WorkerV8 X:");
123 static v8::Handle<v8::Value> Run(const v8::Arguments& args) {
124 WorkerV8 *workerV8 = ObjectWrap::Unwrap<WorkerV8>(args.This());
125 DBG("WorkerV8::Run(args) E:");
126 workerV8->handler_->Run();
127 DBG("WorkerV8::Run(args) X:");
128 return v8::Undefined();
131 static v8::Handle<v8::Value> Add(const v8::Arguments& args) {
132 DBG("WorkerV8::Add(args) E:");
133 WorkerV8 *workerV8 = ObjectWrap::Unwrap<WorkerV8>(args.This());
135 // Validate one argument to add
136 if (args.Length() != 1) {
137 DBG("WorkerV8::Add(args) X: expecting one param");
138 return v8::ThrowException(v8::String::New("Add has no parameter"));
140 ArgInfo *ai = workerV8->ObtainArgInfo();
141 ai->js_this = v8::Persistent<v8::Object>::New( args.This() );
142 ai->value = v8::Persistent<v8::Value>::New( args[0] );
144 workerV8->handler_->Add(ai);
145 DBG("WorkerV8::Add(args) X:");
146 return v8::Undefined();
149 static v8::Handle<v8::Value> AddDelayed(const v8::Arguments& args) {
150 DBG("WorkerV8::AddDelayed(args) E:");
151 WorkerV8 *workerV8 = ObjectWrap::Unwrap<WorkerV8>(args.This());
153 // Validate two argument to addDelayed
154 if (args.Length() != 2) {
155 DBG("WorkerV8::AddDelayed(args) X: expecting two params");
156 return v8::ThrowException(v8::String::New("AddDelayed expects req delayTime params"));
158 ArgInfo *ai = workerV8->ObtainArgInfo();
159 ai->js_this = v8::Persistent<v8::Object>::New( args.This() );
160 ai->value = v8::Persistent<v8::Value>::New( args[0] );
161 v8::Handle<v8::Value> v8DelayMs(args[1]->ToObject());
162 int32_t delay_ms = v8DelayMs->Int32Value();
163 workerV8->handler_->AddDelayed(ai, delay_ms);
165 DBG("WorkerV8::AddDelayed(args) X:");
166 return v8::Undefined();
169 static v8::Handle<v8::Value> NewWorkerV8(const v8::Arguments& args) {
170 DBG("WorkerV8::NewWorkerV8 E: args.Length()=%d", args.Length());
171 WorkerV8 *worker = new WorkerV8(args.This(), args[0]);
172 DBG("WorkerV8::NewWorkerV8 X:");
173 return worker->handle_;
177 void WorkerV8Init() {
178 DBG("WorkerV8Init E:");
179 v8::HandleScope handle_scope;
181 WorkerV8Template = v8::Persistent<v8::FunctionTemplate>::New(
182 v8::FunctionTemplate::New(WorkerV8::NewWorkerV8));
183 WorkerV8Template->SetClassName(v8::String::New("Worker"));
184 // native self (Field 0 is handle_) field count is at least 1
185 WorkerV8Template->InstanceTemplate()->SetInternalFieldCount(1);
187 // Set prototype methods
188 SET_PROTOTYPE_METHOD(WorkerV8Template, "run", WorkerV8::Run);
189 SET_PROTOTYPE_METHOD(WorkerV8Template, "add", WorkerV8::Add);
190 SET_PROTOTYPE_METHOD(WorkerV8Template, "addDelayed", WorkerV8::AddDelayed);
192 DBG("WorkerV8Init X:");
195 void testWorkerV8(v8::Handle<v8::Context> context) {
196 ALOGD("testWorkerV8 E: ********");
197 v8::HandleScope handle_scope;
199 v8::TryCatch try_catch;
200 try_catch.SetVerbose(true);
202 ALOGD("testWorkerV8 runJs");
203 runJs(context, &try_catch, "local-string",
204 "var w1 = new Worker(function (msg) {"
205 " print('w1: ' + msg);\n"
208 "var w2 = new Worker(function (msg) {"
209 " print('w2: ' + msg);\n"
212 "w2.addDelayed('three', 1000);\n"
215 "w1.addDelayed('four', 2000);\n"
217 ALOGD("testWorkerV8 X: ********");
220 extern void WorkerV8ObjectTemplateInit(v8::Handle<v8::ObjectTemplate> target) {
221 DBG("WorkerV8ObjectTemplateInit(target) E:");
222 target->Set(v8::String::New("Worker"), WorkerV8Template);
223 DBG("WorkerV8ObjectTemplateInit(target) X:\n");