OSDN Git Service

Add LTE location information to DATA_REGISTRATION_STATE
[android-x86/hardware-ril.git] / mock-ril / src / cpp / worker_v8.cpp
1 /**
2  * Copyright (C) 2010 The Android Open Source Project
3  *
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
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
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.
15  */
16
17 #include <queue>
18 #include <v8.h>
19
20 #include "logging.h"
21 #include "js_support.h"
22 #include "node_object_wrap.h"
23 #include "node_util.h"
24 #include "util.h"
25 #include "worker.h"
26
27 #include "worker_v8.h"
28
29
30 //#define WORKER_V8_V8_DEBUG
31 #ifdef  WORKER_V8_V8_DEBUG
32
33 #define DBG(...) ALOGD(__VA_ARGS__)
34
35 #else
36
37 #define DBG(...)
38
39 #endif
40
41 v8::Persistent<v8::FunctionTemplate> WorkerV8Template;
42
43 class WorkerV8 : public ObjectWrap {
44   private:
45     friend class Handler;
46
47
48     struct ArgInfo {
49         v8::Persistent<v8::Object> js_this;
50         v8::Persistent<v8::Value> value;
51     };
52
53     pthread_mutex_t ai_free_list_mutex_;
54     std::queue<ArgInfo *>  ai_free_list_;
55
56     ArgInfo *ObtainArgInfo() {
57         ArgInfo *ai;
58         pthread_mutex_lock(&ai_free_list_mutex_);
59         if (ai_free_list_.size() == 0) {
60             ai = new ArgInfo();
61         } else {
62             ai = ai_free_list_.front();
63             ai_free_list_.pop();
64         }
65         pthread_mutex_unlock(&ai_free_list_mutex_);
66         return ai;
67     }
68
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_);
73     }
74
75     class Handler : public WorkerQueue {
76       private:
77         v8::Persistent<v8::Value> functionValue_;
78         WorkerV8 *worker_;
79
80       public:
81         Handler(WorkerV8 *worker, v8::Handle<v8::Value> value)
82             : worker_(worker) {
83             functionValue_ = v8::Persistent<v8::Value>::New(value);
84         }
85
86         void Process(void *param) {
87             DBG("Handler::Process: E");
88
89             v8::Locker locker;
90             v8::HandleScope handle_scope;
91             v8::TryCatch try_catch;
92             try_catch.SetVerbose(true);
93
94             ArgInfo *ai = (ArgInfo*)param;
95             v8::Handle<v8::Value> args(ai->value);
96             v8::Function::Cast(*functionValue_)->Call(ai->js_this, 1, &args);
97
98             ai->js_this.Dispose();
99             ai->value.Dispose();
100
101             worker_->ReleaseArgInfo(ai);
102
103             DBG("Handler::Process: X");
104         }
105     };
106
107     Handler *handler_;
108
109   public:
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);
114         Wrap(self);
115         DBG("WorkerV8::WorkerV8 X: this=%p handler_=%p", this, handler_);
116     }
117
118     virtual ~WorkerV8() {
119         DBG("~WorkerV8::WorkerV8 E:");
120         DBG("~WorkerV8::WorkerV8 X:");
121     }
122
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();
129     }
130
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());
134
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"));
139         }
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] );
143
144         workerV8->handler_->Add(ai);
145         DBG("WorkerV8::Add(args) X:");
146         return v8::Undefined();
147     }
148
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());
152
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"));
157         }
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);
164
165         DBG("WorkerV8::AddDelayed(args) X:");
166         return v8::Undefined();
167     }
168
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_;
174     }
175 };
176
177 void WorkerV8Init() {
178     DBG("WorkerV8Init E:");
179     v8::HandleScope handle_scope;
180
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);
186
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);
191
192     DBG("WorkerV8Init X:");
193 }
194
195 void testWorkerV8(v8::Handle<v8::Context> context) {
196     ALOGD("testWorkerV8 E: ********");
197     v8::HandleScope handle_scope;
198
199     v8::TryCatch try_catch;
200     try_catch.SetVerbose(true);
201
202     ALOGD("testWorkerV8 runJs");
203     runJs(context, &try_catch, "local-string",
204         "var w1 = new Worker(function (msg) {"
205         "     print('w1: ' + msg);\n"
206         "});\n"
207         "w1.run();\n"
208         "var w2 = new Worker(function (msg) {"
209         "     print('w2: ' + msg);\n"
210         "});\n"
211         "w2.run();\n"
212         "w2.addDelayed('three', 1000);\n"
213         "w2.add('one');\n"
214         "w1.add('two');\n"
215         "w1.addDelayed('four', 2000);\n"
216     );
217     ALOGD("testWorkerV8 X: ********");
218 }
219
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");
224 }