Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(676)

Side by Side Diff: frog/lib/isolate_serialization.dart

Issue 9422019: isolates refactor: this change introduces 'dart:isolate' as a library. This is a (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: '' Created 8 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « frog/lib/isolate.dart ('k') | frog/lib/newisolate.dart » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 // Copyright (c) 2012, 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 /**
6 * Abstract visitor for dart objects that can be passed as messages between any
7 * isolates.
8 */
9 class MessageTraverser {
10 static bool isPrimitive(x) {
11 return (x === null) || (x is String) || (x is num) || (x is bool);
12 }
13
14 MessageTraverser();
15
16 /** Visitor's entry point. */
17 traverse(var x) {
18 if (isPrimitive(x)) return visitPrimitive(x);
19 _taggedObjects = new List();
20 var result;
21 try {
22 result = _dispatch(x);
23 } finally {
24 _cleanup();
25 }
26 return result;
27 }
28
29 /** Remove all information injected in the native objects by this visitor. */
30 void _cleanup() {
31 int len = _taggedObjects.length;
32 for (int i = 0; i < len; i++) {
33 _clearAttachedInfo(_taggedObjects[i]);
34 }
35 _taggedObjects = null;
36 }
37
38 /** Injects into the native object some information used by the visitor. */
39 void _attachInfo(var o, var info) {
40 _taggedObjects.add(o);
41 _setAttachedInfo(o, info);
42 }
43
44 /** Retrieves any information stored in the native object [o]. */
45 _getInfo(var o) {
46 return _getAttachedInfo(o);
47 }
48
49 _dispatch(var x) {
50 if (isPrimitive(x)) return visitPrimitive(x);
51 if (x is List) return visitList(x);
52 if (x is Map) return visitMap(x);
53 if (x is NativeJsSendPort) return visitNativeJsSendPort(x);
54 if (x is WorkerSendPort) return visitWorkerSendPort(x);
55 if (x is BufferingSendPort) return visitBufferingSendPort(x);
56 if (x is ReceivePortImpl) return visitReceivePort(x);
57 if (x is ReceivePortSingleShotImpl) return visitReceivePortSingleShot(x);
58 // TODO(floitsch): make this a real exception. (which one)?
59 throw "Message serialization: Illegal value $x passed";
60 }
61
62 abstract visitPrimitive(x);
63 abstract visitList(List x);
64 abstract visitMap(Map x);
65 abstract visitNativeJsSendPort(NativeJsSendPort x);
66 abstract visitWorkerSendPort(WorkerSendPort x);
67 abstract visitBufferingSendPort(BufferingSendPort x);
68 abstract visitReceivePort(ReceivePortImpl x);
69 abstract visitReceivePortSingleShot(ReceivePortSingleShotImpl x);
70
71 List _taggedObjects;
72
73 _clearAttachedInfo(var o) native
74 "o['__MessageTraverser__attached_info__'] = (void 0);";
75
76 _setAttachedInfo(var o, var info) native
77 "o['__MessageTraverser__attached_info__'] = info;";
78
79 _getAttachedInfo(var o) native
80 "return o['__MessageTraverser__attached_info__'];";
81
82 _visitNativeOrWorkerPort(SendPort p) {
83 if (p is NativeJsSendPort) return visitNativeJsSendPort(p);
84 if (p is WorkerSendPort) return visitWorkerSendPort(p);
85 throw "Illegal underlying port $p";
86 }
87 }
88
89 /** A visitor that recursively copies a message. */
90 class Copier extends MessageTraverser {
91 Copier() : super();
92
93 visitPrimitive(x) => x;
94
95 List visitList(List list) {
96 List copy = _getInfo(list);
97 if (copy !== null) return copy;
98
99 int len = list.length;
100
101 // TODO(floitsch): we loose the generic type of the List.
102 copy = new List(len);
103 _attachInfo(list, copy);
104 for (int i = 0; i < len; i++) {
105 copy[i] = _dispatch(list[i]);
106 }
107 return copy;
108 }
109
110 Map visitMap(Map map) {
111 Map copy = _getInfo(map);
112 if (copy !== null) return copy;
113
114 // TODO(floitsch): we loose the generic type of the map.
115 copy = new Map();
116 _attachInfo(map, copy);
117 map.forEach((key, val) {
118 copy[_dispatch(key)] = _dispatch(val);
119 });
120 return copy;
121 }
122
123 SendPort visitNativeJsSendPort(NativeJsSendPort port) {
124 return new NativeJsSendPort(port._receivePort, port._isolateId);
125 }
126
127 SendPort visitWorkerSendPort(WorkerSendPort port) {
128 return new WorkerSendPort(
129 port._workerId, port._isolateId, port._receivePortId);
130 }
131
132 SendPort visitBufferingSendPort(BufferingSendPort port) {
133 if (port._port != null) {
134 return _visitNativeOrWorkerPort(port._port);
135 } else {
136 // TODO(floitsch): Use real exception (which one?).
137 throw "internal error: must call _waitForPendingPorts to ensure all"
138 + " ports are resolved at this point.";
139 }
140 }
141
142 SendPort visitReceivePort(ReceivePortImpl port) {
143 return port.toSendPort();
144 }
145
146 SendPort visitReceivePortSingleShot(ReceivePortSingleShotImpl port) {
147 return port.toSendPort();
148 }
149 }
150
151 /** Visitor that serializes a message as a JSON array. */
152 class Serializer extends MessageTraverser {
153 Serializer() : super();
154
155 visitPrimitive(x) => x;
156
157 visitList(List list) {
158 int copyId = _getInfo(list);
159 if (copyId !== null) return ['ref', copyId];
160
161 int id = _nextFreeRefId++;
162 _attachInfo(list, id);
163 var jsArray = _serializeList(list);
164 // TODO(floitsch): we are losing the generic type.
165 return ['list', id, jsArray];
166 }
167
168 visitMap(Map map) {
169 int copyId = _getInfo(map);
170 if (copyId !== null) return ['ref', copyId];
171
172 int id = _nextFreeRefId++;
173 _attachInfo(map, id);
174 var keys = _serializeList(map.getKeys());
175 var values = _serializeList(map.getValues());
176 // TODO(floitsch): we are losing the generic type.
177 return ['map', id, keys, values];
178 }
179
180 visitNativeJsSendPort(NativeJsSendPort port) {
181 return ['sendport', _globalState.currentWorkerId,
182 port._isolateId, port._receivePort._id];
183 }
184
185 visitWorkerSendPort(WorkerSendPort port) {
186 return ['sendport', port._workerId, port._isolateId, port._receivePortId];
187 }
188
189 visitBufferingSendPort(BufferingSendPort port) {
190 if (port._port != null) {
191 return _visitNativeOrWorkerPort(port._port);
192 } else {
193 // TODO(floitsch): Use real exception (which one?).
194 throw "internal error: must call _waitForPendingPorts to ensure all"
195 + " ports are resolved at this point.";
196 }
197 }
198
199 visitReceivePort(ReceivePortImpl port) {
200 return visitNativeJsSendPort(port.toSendPort());;
201 }
202
203 visitReceivePortSingleShot(ReceivePortSingleShotImpl port) {
204 return visitNativeJsSendPort(port.toSendPort());
205 }
206
207 _serializeList(List list) {
208 int len = list.length;
209 var result = new List(len);
210 for (int i = 0; i < len; i++) {
211 result[i] = _dispatch(list[i]);
212 }
213 return result;
214 }
215
216 int _nextFreeRefId = 0;
217 }
218
219 /** Visitor that finds all unresolved [SendPort]s in a message. */
220 class PendingSendPortFinder extends MessageTraverser {
221 List<Future<SendPort>> ports;
222 PendingSendPortFinder() : super(), ports = [];
223
224 visitPrimitive(x) {}
225 visitNativeJsSendPort(NativeJsSendPort port) {}
226 visitWorkerSendPort(WorkerSendPort port) {}
227 visitReceivePort(ReceivePortImpl port) {}
228 visitReceivePortSingleShot(ReceivePortSingleShotImpl port) {}
229
230 visitList(List list) {
231 final visited = _getInfo(list);
232 if (visited !== null) return;
233 _attachInfo(list, true);
234 // TODO(sigmund): replace with the following: (bug #1660)
235 // list.forEach(_dispatch);
236 list.forEach((e) => _dispatch(e));
237 }
238
239 visitMap(Map map) {
240 final visited = _getInfo(map);
241 if (visited !== null) return;
242
243 _attachInfo(map, true);
244 // TODO(sigmund): replace with the following: (bug #1660)
245 // map.getValues().forEach(_dispatch);
246 map.getValues().forEach((e) => _dispatch(e));
247 }
248
249 visitBufferingSendPort(BufferingSendPort port) {
250 if (port._port == null) {
251 ports.add(port._futurePort);
252 }
253 }
254 }
255
256
257 /** Deserializes arrays created with [Serializer]. */
258 class Deserializer {
259 Deserializer();
260
261 static bool isPrimitive(x) {
262 return (x === null) || (x is String) || (x is num) || (x is bool);
263 }
264
265 deserialize(x) {
266 if (isPrimitive(x)) return x;
267 // TODO(floitsch): this should be new HashMap<int, var|Dynamic>()
268 _deserialized = new HashMap();
269 return _deserializeHelper(x);
270 }
271
272 _deserializeHelper(x) {
273 if (isPrimitive(x)) return x;
274 assert(x is List);
275 switch (x[0]) {
276 case 'ref': return _deserializeRef(x);
277 case 'list': return _deserializeList(x);
278 case 'map': return _deserializeMap(x);
279 case 'sendport': return _deserializeSendPort(x);
280 // TODO(floitsch): Use real exception (which one?).
281 default: throw "Unexpected serialized object";
282 }
283 }
284
285 _deserializeRef(List x) {
286 int id = x[1];
287 var result = _deserialized[id];
288 assert(result !== null);
289 return result;
290 }
291
292 List _deserializeList(List x) {
293 int id = x[1];
294 // We rely on the fact that Dart-lists are directly mapped to Js-arrays.
295 List dartList = x[2];
296 _deserialized[id] = dartList;
297 int len = dartList.length;
298 for (int i = 0; i < len; i++) {
299 dartList[i] = _deserializeHelper(dartList[i]);
300 }
301 return dartList;
302 }
303
304 Map _deserializeMap(List x) {
305 Map result = new Map();
306 int id = x[1];
307 _deserialized[id] = result;
308 List keys = x[2];
309 List values = x[3];
310 int len = keys.length;
311 assert(len == values.length);
312 for (int i = 0; i < len; i++) {
313 var key = _deserializeHelper(keys[i]);
314 var value = _deserializeHelper(values[i]);
315 result[key] = value;
316 }
317 return result;
318 }
319
320 SendPort _deserializeSendPort(List x) {
321 int workerId = x[1];
322 int isolateId = x[2];
323 int receivePortId = x[3];
324 // If two isolates are in the same worker, we use NativeJsSendPorts to
325 // deliver messages directly without using postMessage.
326 if (workerId == _globalState.currentWorkerId) {
327 var isolate = _globalState.isolates[isolateId];
328 if (isolate == null) return null; // Isolate has been closed.
329 var receivePort = isolate.lookup(receivePortId);
330 return new NativeJsSendPort(receivePort, isolateId);
331 } else {
332 return new WorkerSendPort(workerId, isolateId, receivePortId);
333 }
334 }
335
336 Map<int, Dynamic> _deserialized;
337 }
OLDNEW
« no previous file with comments | « frog/lib/isolate.dart ('k') | frog/lib/newisolate.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698