OLD | NEW |
1 // Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file |
2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
4 | 4 |
5 #include "include/dart_api.h" | 5 #include "include/dart_api.h" |
6 #include "include/dart_native_api.h" | 6 #include "include/dart_native_api.h" |
7 | 7 |
8 #include "vm/unit_test.h" | 8 #include "vm/unit_test.h" |
9 | 9 |
10 // Custom Isolate Test. | 10 // Custom Isolate Test. |
11 // | 11 // |
12 // This mid-size test uses the Dart Embedding Api to create a custom | 12 // This mid-size test uses the Dart Embedding Api to create a custom |
13 // isolate abstraction. Instead of having a dedicated thread for each | 13 // isolate abstraction. Instead of having a dedicated thread for each |
14 // isolate, as is the case normally, this implementation shares a | 14 // isolate, as is the case normally, this implementation shares a |
15 // single thread among the isolates using an event queue. | 15 // single thread among the isolates using an event queue. |
16 | 16 |
17 namespace dart { | 17 namespace dart { |
18 | 18 |
19 DECLARE_FLAG(bool, trace_shutdown); | 19 DECLARE_FLAG(bool, trace_shutdown); |
20 | 20 |
21 static void native_echo(Dart_NativeArguments args); | 21 static void native_echo(Dart_NativeArguments args); |
22 static void CustomIsolateImpl_start(Dart_NativeArguments args); | 22 static void CustomIsolateImpl_start(Dart_NativeArguments args); |
23 static Dart_NativeFunction NativeLookup(Dart_Handle name, | 23 static Dart_NativeFunction NativeLookup(Dart_Handle name, |
24 int argc, | 24 int argc, |
25 bool* auto_setup_scope); | 25 bool* auto_setup_scope); |
26 | 26 |
27 | |
28 static const char* kCustomIsolateScriptChars = | 27 static const char* kCustomIsolateScriptChars = |
29 "import 'dart:isolate';\n" | 28 "import 'dart:isolate';\n" |
30 "\n" | 29 "\n" |
31 "final RawReceivePort mainPort = new RawReceivePort();\n" | 30 "final RawReceivePort mainPort = new RawReceivePort();\n" |
32 "final SendPort mainSendPort = mainPort.sendPort;\n" | 31 "final SendPort mainSendPort = mainPort.sendPort;\n" |
33 "\n" | 32 "\n" |
34 "echo(arg) native \"native_echo\";\n" | 33 "echo(arg) native \"native_echo\";\n" |
35 "\n" | 34 "\n" |
36 "class CustomIsolateImpl implements CustomIsolate {\n" | 35 "class CustomIsolateImpl implements CustomIsolate {\n" |
37 " CustomIsolateImpl(String entry) : _entry = entry{\n" | 36 " CustomIsolateImpl(String entry) : _entry = entry{\n" |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
70 " var receivePort = new RawReceivePort();\n" | 69 " var receivePort = new RawReceivePort();\n" |
71 " SendPort port = isolate.spawn();\n" | 70 " SendPort port = isolate.spawn();\n" |
72 " port.send([42, receivePort.sendPort]);\n" | 71 " port.send([42, receivePort.sendPort]);\n" |
73 " receivePort.handler = (message) {\n" | 72 " receivePort.handler = (message) {\n" |
74 " receivePort.close();\n" | 73 " receivePort.close();\n" |
75 " echo('Received: $message');\n" | 74 " echo('Received: $message');\n" |
76 " };\n" | 75 " };\n" |
77 " return 'success';\n" | 76 " return 'success';\n" |
78 "}\n"; | 77 "}\n"; |
79 | 78 |
80 | |
81 // An entry in our event queue. | 79 // An entry in our event queue. |
82 class Event { | 80 class Event { |
83 protected: | 81 protected: |
84 explicit Event(Dart_Isolate isolate) : isolate_(isolate), next_(NULL) {} | 82 explicit Event(Dart_Isolate isolate) : isolate_(isolate), next_(NULL) {} |
85 | 83 |
86 public: | 84 public: |
87 virtual ~Event() {} | 85 virtual ~Event() {} |
88 virtual void Process() = 0; | 86 virtual void Process() = 0; |
89 | 87 |
90 Dart_Isolate isolate() const { return isolate_; } | 88 Dart_Isolate isolate() const { return isolate_; } |
91 | 89 |
92 private: | 90 private: |
93 friend class EventQueue; | 91 friend class EventQueue; |
94 Dart_Isolate isolate_; | 92 Dart_Isolate isolate_; |
95 Event* next_; | 93 Event* next_; |
96 }; | 94 }; |
97 | 95 |
98 | |
99 // A simple event queue for our test. | 96 // A simple event queue for our test. |
100 class EventQueue { | 97 class EventQueue { |
101 public: | 98 public: |
102 EventQueue() { head_ = NULL; } | 99 EventQueue() { head_ = NULL; } |
103 | 100 |
104 void Add(Event* event) { | 101 void Add(Event* event) { |
105 if (head_ == NULL) { | 102 if (head_ == NULL) { |
106 head_ = event; | 103 head_ = event; |
107 tail_ = event; | 104 tail_ = event; |
108 } else { | 105 } else { |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
146 } | 143 } |
147 tail_ = prev; | 144 tail_ = prev; |
148 } | 145 } |
149 | 146 |
150 private: | 147 private: |
151 Event* head_; | 148 Event* head_; |
152 Event* tail_; | 149 Event* tail_; |
153 }; | 150 }; |
154 EventQueue* event_queue; | 151 EventQueue* event_queue; |
155 | 152 |
156 | |
157 // Start an isolate. | 153 // Start an isolate. |
158 class StartEvent : public Event { | 154 class StartEvent : public Event { |
159 public: | 155 public: |
160 StartEvent(Dart_Isolate isolate, const char* main) | 156 StartEvent(Dart_Isolate isolate, const char* main) |
161 : Event(isolate), main_(main) {} | 157 : Event(isolate), main_(main) {} |
162 | 158 |
163 virtual void Process(); | 159 virtual void Process(); |
164 | 160 |
165 private: | 161 private: |
166 const char* main_; | 162 const char* main_; |
167 }; | 163 }; |
168 | 164 |
169 | |
170 void StartEvent::Process() { | 165 void StartEvent::Process() { |
171 OS::Print(">> StartEvent with isolate(%p)--\n", isolate()); | 166 OS::Print(">> StartEvent with isolate(%p)--\n", isolate()); |
172 Dart_EnterIsolate(isolate()); | 167 Dart_EnterIsolate(isolate()); |
173 Dart_EnterScope(); | 168 Dart_EnterScope(); |
174 Dart_Handle result; | 169 Dart_Handle result; |
175 | 170 |
176 Dart_Handle lib = Dart_LookupLibrary(NewString(TestCase::url())); | 171 Dart_Handle lib = Dart_LookupLibrary(NewString(TestCase::url())); |
177 EXPECT_VALID(lib); | 172 EXPECT_VALID(lib); |
178 | 173 |
179 result = Dart_Invoke(lib, NewString(main_), 0, NULL); | 174 result = Dart_Invoke(lib, NewString(main_), 0, NULL); |
180 EXPECT_VALID(result); | 175 EXPECT_VALID(result); |
181 free(const_cast<char*>(main_)); | 176 free(const_cast<char*>(main_)); |
182 main_ = NULL; | 177 main_ = NULL; |
183 | 178 |
184 Dart_SetMessageNotifyCallback(NULL); | 179 Dart_SetMessageNotifyCallback(NULL); |
185 Dart_ExitScope(); | 180 Dart_ExitScope(); |
186 Dart_ExitIsolate(); | 181 Dart_ExitIsolate(); |
187 } | 182 } |
188 | 183 |
189 | |
190 // Notify an isolate of a pending message. | 184 // Notify an isolate of a pending message. |
191 class MessageEvent : public Event { | 185 class MessageEvent : public Event { |
192 public: | 186 public: |
193 explicit MessageEvent(Dart_Isolate isolate) : Event(isolate) {} | 187 explicit MessageEvent(Dart_Isolate isolate) : Event(isolate) {} |
194 | 188 |
195 ~MessageEvent() {} | 189 ~MessageEvent() {} |
196 | 190 |
197 virtual void Process(); | 191 virtual void Process(); |
198 }; | 192 }; |
199 | 193 |
200 | |
201 void MessageEvent::Process() { | 194 void MessageEvent::Process() { |
202 OS::Print("$$ MessageEvent with isolate(%p)\n", isolate()); | 195 OS::Print("$$ MessageEvent with isolate(%p)\n", isolate()); |
203 Dart_EnterIsolate(isolate()); | 196 Dart_EnterIsolate(isolate()); |
204 Dart_EnterScope(); | 197 Dart_EnterScope(); |
205 | 198 |
206 Dart_Handle result = Dart_HandleMessage(); | 199 Dart_Handle result = Dart_HandleMessage(); |
207 EXPECT_VALID(result); | 200 EXPECT_VALID(result); |
208 | 201 |
209 if (!Dart_HasLivePorts()) { | 202 if (!Dart_HasLivePorts()) { |
210 OS::Print("<< Shutting down isolate(%p)\n", isolate()); | 203 OS::Print("<< Shutting down isolate(%p)\n", isolate()); |
211 event_queue->RemoveEventsForIsolate(isolate()); | 204 event_queue->RemoveEventsForIsolate(isolate()); |
212 Dart_SetMessageNotifyCallback(NULL); | 205 Dart_SetMessageNotifyCallback(NULL); |
213 Dart_ExitScope(); | 206 Dart_ExitScope(); |
214 Dart_ShutdownIsolate(); | 207 Dart_ShutdownIsolate(); |
215 } else { | 208 } else { |
216 Dart_ExitScope(); | 209 Dart_ExitScope(); |
217 Dart_ExitIsolate(); | 210 Dart_ExitIsolate(); |
218 } | 211 } |
219 ASSERT(Dart_CurrentIsolate() == NULL); | 212 ASSERT(Dart_CurrentIsolate() == NULL); |
220 } | 213 } |
221 | 214 |
222 | |
223 static void NotifyMessage(Dart_Isolate dest_isolate) { | 215 static void NotifyMessage(Dart_Isolate dest_isolate) { |
224 OS::Print("-- Notify isolate(%p) of pending message --\n", dest_isolate); | 216 OS::Print("-- Notify isolate(%p) of pending message --\n", dest_isolate); |
225 OS::Print("-- Adding MessageEvent to queue --\n"); | 217 OS::Print("-- Adding MessageEvent to queue --\n"); |
226 event_queue->Add(new MessageEvent(dest_isolate)); | 218 event_queue->Add(new MessageEvent(dest_isolate)); |
227 } | 219 } |
228 | 220 |
229 | |
230 static Dart_NativeFunction NativeLookup(Dart_Handle name, | 221 static Dart_NativeFunction NativeLookup(Dart_Handle name, |
231 int argc, | 222 int argc, |
232 bool* auto_setup_scope) { | 223 bool* auto_setup_scope) { |
233 ASSERT(auto_setup_scope != NULL); | 224 ASSERT(auto_setup_scope != NULL); |
234 *auto_setup_scope = true; | 225 *auto_setup_scope = true; |
235 const char* name_str = NULL; | 226 const char* name_str = NULL; |
236 EXPECT(Dart_IsString(name)); | 227 EXPECT(Dart_IsString(name)); |
237 EXPECT_VALID(Dart_StringToCString(name, &name_str)); | 228 EXPECT_VALID(Dart_StringToCString(name, &name_str)); |
238 if (strcmp(name_str, "native_echo") == 0) { | 229 if (strcmp(name_str, "native_echo") == 0) { |
239 return &native_echo; | 230 return &native_echo; |
240 } else if (strcmp(name_str, "CustomIsolateImpl_start") == 0) { | 231 } else if (strcmp(name_str, "CustomIsolateImpl_start") == 0) { |
241 return &CustomIsolateImpl_start; | 232 return &CustomIsolateImpl_start; |
242 } | 233 } |
243 return NULL; | 234 return NULL; |
244 } | 235 } |
245 | 236 |
246 | |
247 char* saved_echo = NULL; | 237 char* saved_echo = NULL; |
248 static void native_echo(Dart_NativeArguments args) { | 238 static void native_echo(Dart_NativeArguments args) { |
249 Dart_EnterScope(); | 239 Dart_EnterScope(); |
250 Dart_Handle arg = Dart_GetNativeArgument(args, 0); | 240 Dart_Handle arg = Dart_GetNativeArgument(args, 0); |
251 Dart_Handle toString = Dart_ToString(arg); | 241 Dart_Handle toString = Dart_ToString(arg); |
252 EXPECT_VALID(toString); | 242 EXPECT_VALID(toString); |
253 const char* c_str = NULL; | 243 const char* c_str = NULL; |
254 EXPECT_VALID(Dart_StringToCString(toString, &c_str)); | 244 EXPECT_VALID(Dart_StringToCString(toString, &c_str)); |
255 if (saved_echo) { | 245 if (saved_echo) { |
256 free(saved_echo); | 246 free(saved_echo); |
257 } | 247 } |
258 saved_echo = strdup(c_str); | 248 saved_echo = strdup(c_str); |
259 OS::Print("-- (isolate=%p) %s\n", Dart_CurrentIsolate(), c_str); | 249 OS::Print("-- (isolate=%p) %s\n", Dart_CurrentIsolate(), c_str); |
260 Dart_ExitScope(); | 250 Dart_ExitScope(); |
261 } | 251 } |
262 | 252 |
263 | |
264 static void CustomIsolateImpl_start(Dart_NativeArguments args) { | 253 static void CustomIsolateImpl_start(Dart_NativeArguments args) { |
265 OS::Print("-- Enter: CustomIsolateImpl_start --\n"); | 254 OS::Print("-- Enter: CustomIsolateImpl_start --\n"); |
266 | 255 |
267 // We would probably want to pass in the this pointer too, so we | 256 // We would probably want to pass in the this pointer too, so we |
268 // could associate the CustomIsolateImpl instance with the | 257 // could associate the CustomIsolateImpl instance with the |
269 // Dart_Isolate by storing it in a native field. | 258 // Dart_Isolate by storing it in a native field. |
270 EXPECT_EQ(1, Dart_GetNativeArgumentCount(args)); | 259 EXPECT_EQ(1, Dart_GetNativeArgumentCount(args)); |
271 Dart_Handle param = Dart_GetNativeArgument(args, 0); | 260 Dart_Handle param = Dart_GetNativeArgument(args, 0); |
272 EXPECT_VALID(param); | 261 EXPECT_VALID(param); |
273 EXPECT(Dart_IsString(param)); | 262 EXPECT(Dart_IsString(param)); |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
307 Dart_EnterScope(); | 296 Dart_EnterScope(); |
308 | 297 |
309 Dart_Handle send_port = Dart_NewSendPort(main_port_id); | 298 Dart_Handle send_port = Dart_NewSendPort(main_port_id); |
310 EXPECT_VALID(send_port); | 299 EXPECT_VALID(send_port); |
311 Dart_SetReturnValue(args, send_port); | 300 Dart_SetReturnValue(args, send_port); |
312 | 301 |
313 OS::Print("-- Exit: CustomIsolateImpl_start --\n"); | 302 OS::Print("-- Exit: CustomIsolateImpl_start --\n"); |
314 Dart_ExitScope(); | 303 Dart_ExitScope(); |
315 } | 304 } |
316 | 305 |
317 | |
318 VM_UNIT_TEST_CASE(CustomIsolates) { | 306 VM_UNIT_TEST_CASE(CustomIsolates) { |
319 bool saved_flag = FLAG_trace_shutdown; | 307 bool saved_flag = FLAG_trace_shutdown; |
320 FLAG_trace_shutdown = true; | 308 FLAG_trace_shutdown = true; |
321 FLAG_verify_handles = true; | 309 FLAG_verify_handles = true; |
322 #ifdef DEBUG | 310 #ifdef DEBUG |
323 FLAG_verify_on_transition = true; | 311 FLAG_verify_on_transition = true; |
324 #endif | 312 #endif |
325 event_queue = new EventQueue(); | 313 event_queue = new EventQueue(); |
326 | 314 |
327 Dart_Isolate dart_isolate = TestCase::CreateTestIsolate(); | 315 Dart_Isolate dart_isolate = TestCase::CreateTestIsolate(); |
(...skipping 28 matching lines...) Expand all Loading... |
356 OS::Print("-- Finished event loop --\n"); | 344 OS::Print("-- Finished event loop --\n"); |
357 EXPECT_STREQ("Received: 43", saved_echo); | 345 EXPECT_STREQ("Received: 43", saved_echo); |
358 free(saved_echo); | 346 free(saved_echo); |
359 | 347 |
360 delete event_queue; | 348 delete event_queue; |
361 event_queue = NULL; | 349 event_queue = NULL; |
362 FLAG_trace_shutdown = saved_flag; | 350 FLAG_trace_shutdown = saved_flag; |
363 } | 351 } |
364 | 352 |
365 } // namespace dart | 353 } // namespace dart |
OLD | NEW |