OLD | NEW |
1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2014, 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 import "dart:isolate"; | 5 import "dart:isolate"; |
6 import "dart:async"; | 6 import "dart:async"; |
7 import "package:expect/expect.dart"; | 7 import "package:expect/expect.dart"; |
8 import "package:async_helper/async_helper.dart"; | 8 import "package:async_helper/async_helper.dart"; |
9 | 9 |
10 void toplevel(port, message) { port.send("toplevel:$message"); } | 10 void toplevel(port, message) { |
11 Function createFuncToplevel() => (p, m) { p.send(m); }; | 11 port.send("toplevel:$message"); |
| 12 } |
| 13 |
| 14 Function createFuncToplevel() => (p, m) { |
| 15 p.send(m); |
| 16 }; |
| 17 |
12 class C { | 18 class C { |
13 Function initializer; | 19 Function initializer; |
14 Function body; | 20 Function body; |
15 C() : initializer = ((p, m) { throw "initializer"; }) { | 21 C() |
16 body = (p, m) { throw "body"; }; | 22 : initializer = ((p, m) { |
| 23 throw "initializer"; |
| 24 }) { |
| 25 body = (p, m) { |
| 26 throw "body"; |
| 27 }; |
17 } | 28 } |
18 static void staticFunc(port, message) { port.send("static:$message"); } | 29 static void staticFunc(port, message) { |
19 static Function createFuncStatic() => (p, m) { throw "static expr"; }; | 30 port.send("static:$message"); |
20 void instanceMethod(p, m) { throw "instanceMethod"; } | 31 } |
21 Function createFuncMember() => (p, m) { throw "instance expr"; }; | 32 |
22 void call(n, p) { throw "C"; } | 33 static Function createFuncStatic() => (p, m) { |
| 34 throw "static expr"; |
| 35 }; |
| 36 void instanceMethod(p, m) { |
| 37 throw "instanceMethod"; |
| 38 } |
| 39 |
| 40 Function createFuncMember() => (p, m) { |
| 41 throw "instance expr"; |
| 42 }; |
| 43 void call(n, p) { |
| 44 throw "C"; |
| 45 } |
23 } | 46 } |
24 | 47 |
25 class Callable { | 48 class Callable { |
26 void call(p, m) { p.send(["callable", m]); } | 49 void call(p, m) { |
| 50 p.send(["callable", m]); |
| 51 } |
27 } | 52 } |
28 | 53 |
29 | |
30 void main() { | 54 void main() { |
31 asyncStart(); | 55 asyncStart(); |
32 | 56 |
33 // Sendables are top-level functions and static functions only. | 57 // Sendables are top-level functions and static functions only. |
34 testSendable("toplevel", toplevel); | 58 testSendable("toplevel", toplevel); |
35 testSendable("static", C.staticFunc); | 59 testSendable("static", C.staticFunc); |
36 // Unsendables are any closure - instance methods or function expression. | 60 // Unsendables are any closure - instance methods or function expression. |
37 var c = new C(); | 61 var c = new C(); |
38 testUnsendable("instance method", c.instanceMethod); | 62 testUnsendable("instance method", c.instanceMethod); |
39 testUnsendable("static context expression", createFuncToplevel()); | 63 testUnsendable("static context expression", createFuncToplevel()); |
(...skipping 26 matching lines...) Expand all Loading... |
66 testUnsendable("callable object", new Callable().call); | 90 testUnsendable("callable object", new Callable().call); |
67 | 91 |
68 asyncEnd(); | 92 asyncEnd(); |
69 return; | 93 return; |
70 } | 94 } |
71 | 95 |
72 // Create a receive port that expects exactly one message. | 96 // Create a receive port that expects exactly one message. |
73 // Pass the message to `callback` and return the sendPort. | 97 // Pass the message to `callback` and return the sendPort. |
74 SendPort singleMessagePort(callback) { | 98 SendPort singleMessagePort(callback) { |
75 var p; | 99 var p; |
76 p = new RawReceivePort((v) { p.close(); callback(v); }); | 100 p = new RawReceivePort((v) { |
| 101 p.close(); |
| 102 callback(v); |
| 103 }); |
77 return p.sendPort; | 104 return p.sendPort; |
78 } | 105 } |
79 | 106 |
80 // A singleMessagePort that expects the message to be a specific value. | 107 // A singleMessagePort that expects the message to be a specific value. |
81 SendPort expectMessagePort(message) { | 108 SendPort expectMessagePort(message) { |
82 asyncStart(); | 109 asyncStart(); |
83 return singleMessagePort((v) { | 110 return singleMessagePort((v) { |
84 Expect.equals(message, v); | 111 Expect.equals(message, v); |
85 asyncEnd(); | 112 asyncEnd(); |
86 }); | 113 }); |
87 } | 114 } |
88 | 115 |
89 void testSendable(name, func) { | 116 void testSendable(name, func) { |
90 // Function as spawn message. | 117 // Function as spawn message. |
91 Isolate.spawn(callFunc, [func, expectMessagePort("$name:spawn"), "spawn"]); | 118 Isolate.spawn(callFunc, [func, expectMessagePort("$name:spawn"), "spawn"]); |
92 | 119 |
93 // Send function to same isolate. | 120 // Send function to same isolate. |
94 var reply = expectMessagePort("$name:direct"); | 121 var reply = expectMessagePort("$name:direct"); |
95 singleMessagePort(callFunc).send([func, reply, "direct"]); | 122 singleMessagePort(callFunc).send([func, reply, "direct"]); |
96 | 123 |
97 // Send function to other isolate, call it there. | 124 // Send function to other isolate, call it there. |
98 reply = expectMessagePort("$name:other isolate"); | 125 reply = expectMessagePort("$name:other isolate"); |
99 callPort().then((p) { | 126 callPort().then((p) { |
100 p.send([func, reply, "other isolate"]); | 127 p.send([func, reply, "other isolate"]); |
101 }); | 128 }); |
102 | 129 |
103 // Round-trip function trough other isolate. | 130 // Round-trip function trough other isolate. |
104 echoPort((roundtripFunc) { | 131 echoPort((roundtripFunc) { |
105 Expect.identical(func, roundtripFunc, "$name:send through isolate"); | 132 Expect.identical(func, roundtripFunc, "$name:send through isolate"); |
106 }).then((port) { port.send(func); }); | 133 }).then((port) { |
| 134 port.send(func); |
| 135 }); |
107 } | 136 } |
108 | 137 |
109 // Creates a new isolate and a pair of ports that expect a single message | 138 // Creates a new isolate and a pair of ports that expect a single message |
110 // to be sent to the other isolate and back to the callback function. | 139 // to be sent to the other isolate and back to the callback function. |
111 Future<SendPort> echoPort(callback(value)) { | 140 Future<SendPort> echoPort(callback(value)) { |
112 Completer completer = new Completer<SendPort>(); | 141 Completer completer = new Completer<SendPort>(); |
113 SendPort replyPort = singleMessagePort(callback); | 142 SendPort replyPort = singleMessagePort(callback); |
114 RawReceivePort initPort; | 143 RawReceivePort initPort; |
115 initPort = new RawReceivePort((p) { | 144 initPort = new RawReceivePort((p) { |
116 completer.complete(p); | 145 completer.complete(p); |
117 initPort.close(); | 146 initPort.close(); |
118 }); | 147 }); |
119 return Isolate.spawn(_echo, [replyPort, initPort.sendPort]) | 148 return Isolate.spawn(_echo, [replyPort, initPort.sendPort]).then( |
120 .then((isolate) => completer.future); | 149 (isolate) => completer.future); |
121 } | 150 } |
122 | 151 |
123 void _echo(msg) { | 152 void _echo(msg) { |
124 var replyPort = msg[0]; | 153 var replyPort = msg[0]; |
125 RawReceivePort requestPort; | 154 RawReceivePort requestPort; |
126 requestPort = new RawReceivePort((msg) { | 155 requestPort = new RawReceivePort((msg) { |
127 replyPort.send(msg); | 156 replyPort.send(msg); |
128 requestPort.close(); // Single echo only. | 157 requestPort.close(); // Single echo only. |
129 }); | 158 }); |
130 msg[1].send(requestPort.sendPort); | 159 msg[1].send(requestPort.sendPort); |
131 } | 160 } |
132 | 161 |
133 // Creates other isolate that waits for a single message, `msg`, on the returned | 162 // Creates other isolate that waits for a single message, `msg`, on the returned |
134 // port, and executes it as `msg[0](msg[1],msg[2])` in the other isolate. | 163 // port, and executes it as `msg[0](msg[1],msg[2])` in the other isolate. |
135 Future<SendPort> callPort() { | 164 Future<SendPort> callPort() { |
136 Completer completer = new Completer<SendPort>(); | 165 Completer completer = new Completer<SendPort>(); |
137 SendPort initPort = singleMessagePort(completer.complete); | 166 SendPort initPort = singleMessagePort(completer.complete); |
138 return Isolate.spawn(_call, initPort) | 167 return Isolate.spawn(_call, initPort).then((_) => completer.future); |
139 .then((_) => completer.future); | |
140 } | 168 } |
141 | 169 |
142 void _call(initPort) { | 170 void _call(initPort) { |
143 initPort.send(singleMessagePort(callFunc)); | 171 initPort.send(singleMessagePort(callFunc)); |
144 } | 172 } |
145 | 173 |
146 void testUnsendable(name, func) { | 174 void testUnsendable(name, func) { |
147 asyncStart(); | 175 asyncStart(); |
148 Isolate.spawn(nop, func).then((v) => throw "allowed spawn direct?", | 176 Isolate.spawn(nop, func).then((v) => throw "allowed spawn direct?", |
149 onError: (e,s){ asyncEnd(); }); | 177 onError: (e, s) { |
| 178 asyncEnd(); |
| 179 }); |
150 asyncStart(); | 180 asyncStart(); |
151 Isolate.spawn(nop, [func]).then((v) => throw "allowed spawn wrapped?", | 181 Isolate.spawn(nop, [func]).then((v) => throw "allowed spawn wrapped?", |
152 onError: (e,s){ asyncEnd(); }); | 182 onError: (e, s) { |
| 183 asyncEnd(); |
| 184 }); |
153 | 185 |
154 asyncStart(); | 186 asyncStart(); |
155 var noReply = new RawReceivePort((_) { throw "Unexpected message: $_"; }); | 187 var noReply = new RawReceivePort((_) { |
| 188 throw "Unexpected message: $_"; |
| 189 }); |
156 Expect.throws(() { | 190 Expect.throws(() { |
157 noReply.sendPort.send(func); | 191 noReply.sendPort.send(func); |
158 }, null, "send direct"); | 192 }, null, "send direct"); |
159 Expect.throws(() { | 193 Expect.throws(() { |
160 noReply.sendPort.send([func]); | 194 noReply.sendPort.send([func]); |
161 }, null, "send wrapped"); | 195 }, null, "send wrapped"); |
162 scheduleMicrotask(() { | 196 scheduleMicrotask(() { |
163 noReply.close(); | 197 noReply.close(); |
164 asyncEnd(); | 198 asyncEnd(); |
165 }); | 199 }); |
166 | 200 |
167 // Try sending through other isolate. | 201 // Try sending through other isolate. |
168 asyncStart(); | 202 asyncStart(); |
169 echoPort((v) { Expect.equals(0, v); }) | 203 echoPort((v) { |
170 .then((p) { | 204 Expect.equals(0, v); |
171 try { | 205 }).then((p) { |
172 p.send(func); | 206 try { |
173 } finally { | 207 p.send(func); |
174 p.send(0); // Closes echo port. | 208 } finally { |
175 } | 209 p.send(0); // Closes echo port. |
176 }) | 210 } |
177 .then((p) => throw "unreachable 2", | 211 }).then((p) => throw "unreachable 2", onError: (e, s) { |
178 onError: (e, s) {asyncEnd();}); | 212 asyncEnd(); |
| 213 }); |
179 } | 214 } |
180 | 215 |
181 void nop(_) {} | 216 void nop(_) {} |
182 | 217 |
183 void callFunc(message) { | 218 void callFunc(message) { |
184 message[0](message[1], message[2]); | 219 message[0](message[1], message[2]); |
185 } | 220 } |
OLD | NEW |