Flutter Engine
The Flutter Engine
custom_isolate_test.cc
Go to the documentation of this 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
3// BSD-style license that can be found in the LICENSE file.
4
5#include "include/dart_api.h"
7
8#include "vm/unit_test.h"
9
10// Custom Isolate Test.
11//
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
14// isolate, as is the case normally, this implementation shares a
15// single thread among the isolates using an event queue.
16
17namespace dart {
18
19DECLARE_FLAG(bool, trace_shutdown);
20
24 int argc,
25 bool* auto_setup_scope);
26
27static const char* kCustomIsolateScriptChars =
28 R"(
29 import 'dart:isolate';
30
31 final RawReceivePort mainPort = new RawReceivePort();
32 final SendPort mainSendPort = mainPort.sendPort;
33
34 @pragma('vm:external-name', 'native_echo')
35 external void echo(arg);
36
37 class CustomIsolateImpl implements CustomIsolate {
38 CustomIsolateImpl(String entry) : _entry = entry {
39 echo('Constructing isolate');
40 }
41
42 SendPort spawn() {
43 return _start(_entry);
44 }
45
46 @pragma('vm:external-name', 'CustomIsolateImpl_start')
47 external static SendPort _start(entry);
48
49 String _entry;
50 }
51
52 abstract class CustomIsolate {
53 factory CustomIsolate(String entry) = CustomIsolateImpl;
54
55 SendPort spawn();
56 }
57
58 isolateMain() {
59 echo('Running isolateMain');
60 mainPort.handler = (message) {
61 var data = message[0];
62 var replyTo = message[1];
63 echo('Received: $data');
64 replyTo.send(data + 1);
65 mainPort.close();
66 };
67 }
68
69 main() {
70 var isolate = new CustomIsolate("isolateMain");
71 var receivePort = new RawReceivePort();
72 SendPort port = isolate.spawn();
73 port.send([42, receivePort.sendPort]);
74 receivePort.handler = (message) {
75 receivePort.close();
76 echo('Received: $message');
77 };
78 return 'success';
79 }
80 )";
81
82// An entry in our event queue.
83class Event {
84 protected:
85 explicit Event(Dart_Isolate isolate) : isolate_(isolate), next_(nullptr) {}
86
87 public:
88 virtual ~Event() {}
89 virtual void Process() = 0;
90
91 Dart_Isolate isolate() const { return isolate_; }
92
93 private:
94 friend class EventQueue;
95 Dart_Isolate isolate_;
96 Event* next_;
97};
98
99// A simple event queue for our test.
101 public:
102 EventQueue() { head_ = nullptr; }
103
104 void Add(Event* event) {
105 if (head_ == nullptr) {
106 head_ = event;
107 tail_ = event;
108 } else {
109 tail_->next_ = event;
110 tail_ = event;
111 }
112 }
113
115 if (head_ == nullptr) {
116 return nullptr;
117 }
118 Event* tmp = head_;
119 head_ = head_->next_;
120 if (head_ == nullptr) {
121 // Not necessary, but why not.
122 tail_ = nullptr;
123 }
124
125 return tmp;
126 }
127
129 Event* cur = head_;
130 Event* prev = nullptr;
131 while (cur != nullptr) {
132 Event* next = cur->next_;
133 if (cur->isolate() == isolate) {
134 // Remove matching event.
135 if (prev != nullptr) {
136 prev->next_ = next;
137 } else {
138 head_ = next;
139 }
140 delete cur;
141 } else {
142 // Advance.
143 prev = cur;
144 }
145 cur = next;
146 }
147 tail_ = prev;
148 }
149
150 private:
151 Event* head_;
152 Event* tail_;
153};
155
156// Start an isolate.
157class StartEvent : public Event {
158 public:
160 : Event(isolate), main_(main) {}
161
162 virtual void Process();
163
164 private:
165 const char* main_;
166};
167
169 OS::PrintErr(">> StartEvent with isolate(%p)--\n", isolate());
173
175 EXPECT_VALID(lib);
176
177 result = Dart_Invoke(lib, NewString(main_), 0, nullptr);
179 free(const_cast<char*>(main_));
180 main_ = nullptr;
181
185}
186
187// Notify an isolate of a pending message.
188class MessageEvent : public Event {
189 public:
191
193
194 virtual void Process();
195};
196
198 OS::PrintErr("$$ MessageEvent with isolate(%p)\n", isolate());
201
204
205 if (!Dart_HasLivePorts()) {
206 OS::PrintErr("<< Shutting down isolate(%p)\n", isolate());
211 } else {
214 }
215 ASSERT(Dart_CurrentIsolate() == nullptr);
216}
217
218static void NotifyMessage(Dart_Isolate dest_isolate) {
219 OS::PrintErr("-- Notify isolate(%p) of pending message --\n", dest_isolate);
220 OS::PrintErr("-- Adding MessageEvent to queue --\n");
221 event_queue->Add(new MessageEvent(dest_isolate));
222}
223
225 int argc,
226 bool* auto_setup_scope) {
227 ASSERT(auto_setup_scope != nullptr);
228 *auto_setup_scope = true;
229 const char* name_str = nullptr;
232 if (strcmp(name_str, "native_echo") == 0) {
233 return &native_echo;
234 } else if (strcmp(name_str, "CustomIsolateImpl_start") == 0) {
236 }
237 return nullptr;
238}
239
240char* saved_echo = nullptr;
244 Dart_Handle toString = Dart_ToString(arg);
245 EXPECT_VALID(toString);
246 const char* c_str = nullptr;
247 EXPECT_VALID(Dart_StringToCString(toString, &c_str));
248 if (saved_echo != nullptr) {
249 free(saved_echo);
250 }
251 saved_echo = Utils::StrDup(c_str);
252 OS::PrintErr("-- (isolate=%p) %s\n", Dart_CurrentIsolate(), c_str);
254}
255
257 OS::PrintErr("-- Enter: CustomIsolateImpl_start --\n");
258
259 // We would probably want to pass in the this pointer too, so we
260 // could associate the CustomIsolateImpl instance with the
261 // Dart_Isolate by storing it in a native field.
262 EXPECT_EQ(1, Dart_GetNativeArgumentCount(args));
264 EXPECT_VALID(param);
265 EXPECT(Dart_IsString(param));
266 const char* isolate_main = nullptr;
267 EXPECT_VALID(Dart_StringToCString(param, &isolate_main));
268 isolate_main = Utils::StrDup(isolate_main);
269
270 // Save current isolate.
271 Dart_Isolate saved_isolate = Dart_CurrentIsolate();
273
274 // Create a new Dart_Isolate.
276 EXPECT(new_isolate != nullptr);
279 // Reload all the test classes here.
280 //
281 // TODO(turnidge): Use the create isolate callback instead?
282 Dart_Handle lib =
284 EXPECT_VALID(lib);
285
286 Dart_Handle main_send_port = Dart_GetField(lib, NewString("mainSendPort"));
287 EXPECT_VALID(main_send_port);
288 Dart_Port main_port_id;
289 Dart_Handle err = Dart_SendPortGetId(main_send_port, &main_port_id);
290 EXPECT_VALID(err);
291
292 OS::PrintErr("-- Adding StartEvent to queue --\n");
293 event_queue->Add(new StartEvent(new_isolate, isolate_main));
294
295 // Restore the original isolate.
298 Dart_EnterIsolate(saved_isolate);
300
301 Dart_Handle send_port = Dart_NewSendPort(main_port_id);
302 EXPECT_VALID(send_port);
303 Dart_SetReturnValue(args, send_port);
304
305 OS::PrintErr("-- Exit: CustomIsolateImpl_start --\n");
307}
308
309VM_UNIT_TEST_CASE(CustomIsolates) {
310 bool saved_flag = FLAG_trace_shutdown;
311 FLAG_trace_shutdown = true;
312 event_queue = new EventQueue();
313
315 EXPECT(dart_isolate != nullptr);
319
320 // Create a test library.
321 Dart_Handle lib =
323 EXPECT_VALID(lib);
324
325 // Run main.
326 result = Dart_Invoke(lib, NewString("main"), 0, nullptr);
329 const char* result_str = nullptr;
331 EXPECT_STREQ("success", result_str);
332
335
336 OS::PrintErr("-- Starting event loop --\n");
337 Event* event = event_queue->Get();
338 while (event != nullptr) {
339 event->Process();
340 delete event;
341 event = event_queue->Get();
342 }
343 OS::PrintErr("-- Finished event loop --\n");
344 EXPECT_STREQ("Received: 43", saved_echo);
345 free(saved_echo);
346
347 delete event_queue;
348 event_queue = nullptr;
349 FLAG_trace_shutdown = saved_flag;
350}
351
352} // namespace dart
static float next(float f)
static float prev(float f)
#define EXPECT(type, expectedAlignment, expectedSize)
void Add(Event *event)
void RemoveEventsForIsolate(Dart_Isolate isolate)
Event(Dart_Isolate isolate)
Dart_Isolate isolate() const
virtual void Process()=0
MessageEvent(Dart_Isolate isolate)
static void static void PrintErr(const char *format,...) PRINTF_ATTRIBUTE(1
virtual void Process()
StartEvent(Dart_Isolate isolate, const char *main)
static Dart_Handle LoadTestScript(const char *script, Dart_NativeEntryResolver resolver, const char *lib_uri=RESOLVED_USER_TEST_URI, bool finalize=true, bool allow_compile_errors=false)
Definition: unit_test.cc:436
static const char * url()
Definition: unit_test.cc:185
static Dart_Isolate CreateTestIsolate(const char *name=nullptr, void *isolate_group_data=nullptr, void *isolate_data=nullptr)
Definition: unit_test.cc:140
static char * StrDup(const char *s)
int64_t Dart_Port
Definition: dart_api.h:1525
struct _Dart_Handle * Dart_Handle
Definition: dart_api.h:258
struct _Dart_Isolate * Dart_Isolate
Definition: dart_api.h:88
struct _Dart_NativeArguments * Dart_NativeArguments
Definition: dart_api.h:3019
void(* Dart_NativeFunction)(Dart_NativeArguments arguments)
Definition: dart_api.h:3207
#define ASSERT(E)
G_BEGIN_DECLS G_MODULE_EXPORT FlValue * args
FlKeyEvent * event
GAsyncResult * result
Definition: dart_vm.cc:33
DART_EXPORT void Dart_EnterScope()
const char *const name
DART_EXPORT void Dart_EnterIsolate(Dart_Isolate isolate)
DART_EXPORT Dart_Handle Dart_Invoke(Dart_Handle target, Dart_Handle name, int number_of_arguments, Dart_Handle *arguments)
static void NotifyMessage(Dart_Isolate dest_isolate)
static void native_echo(Dart_NativeArguments args)
DART_EXPORT void Dart_SetReturnValue(Dart_NativeArguments args, Dart_Handle retval)
DART_EXPORT Dart_Handle Dart_GetField(Dart_Handle container, Dart_Handle name)
DART_EXPORT Dart_Handle Dart_ToString(Dart_Handle object)
char * saved_echo
DART_EXPORT Dart_Isolate Dart_CurrentIsolate()
DART_EXPORT Dart_Handle Dart_NewSendPort(Dart_Port port_id)
static const char * kCustomIsolateScriptChars
DART_EXPORT Dart_Handle Dart_GetNativeArgument(Dart_NativeArguments args, int index)
DART_EXPORT void Dart_ExitIsolate()
Dart_Handle NewString(const char *str)
DART_EXPORT void Dart_ExitScope()
static Dart_NativeFunction NativeLookup(Dart_Handle name, int argc, bool *auto_setup_scope)
DART_EXPORT void Dart_SetMessageNotifyCallback(Dart_MessageNotifyCallback message_notify_callback)
EventQueue * event_queue
DART_EXPORT Dart_Handle Dart_LookupLibrary(Dart_Handle url)
DART_EXPORT int Dart_GetNativeArgumentCount(Dart_NativeArguments args)
DART_EXPORT bool Dart_IsString(Dart_Handle object)
DART_EXPORT Dart_Handle Dart_StringToCString(Dart_Handle object, const char **cstr)
DART_EXPORT Dart_Handle Dart_SendPortGetId(Dart_Handle port, Dart_Port *port_id)
DART_EXPORT void Dart_ShutdownIsolate()
DART_EXPORT bool Dart_HasLivePorts()
static void CustomIsolateImpl_start(Dart_NativeArguments args)
DART_EXPORT Dart_Handle Dart_HandleMessage()
DECLARE_FLAG(bool, show_invisible_frames)
VM_UNIT_TEST_CASE(DirectoryCurrentNoScope)
Definition: main.py:1
#define EXPECT_VALID(handle)
Definition: unit_test.h:643