質問編集履歴

2

失敗例を追加。

2016/02/02 05:39

投稿

twinbird
twinbird

スコア12

test CHANGED
File without changes
test CHANGED
@@ -33,3 +33,215 @@
33
33
 
34
34
 
35
35
  setIntervalの実装方法をご教授願います。
36
+
37
+
38
+
39
+ ちなみに、以下が1つのJSRuntimeのみを用いてマルチスレッドで動かして失敗した例です。
40
+
41
+ ```C++
42
+
43
+ /*
44
+
45
+ SpiderMonkeyで同一のJSRuntimeを別スレッドで使用して、エラーになる例。
46
+
47
+ */
48
+
49
+
50
+
51
+ #include <iostream>
52
+
53
+ #include <thread>
54
+
55
+ #include <jsapi.h>
56
+
57
+
58
+
59
+ using namespace std;
60
+
61
+
62
+
63
+ /**
64
+
65
+ * 実行するJavaScript。
66
+
67
+ * spawn関数は、引数のクロージャを別のスレッドで評価する。
68
+
69
+ * ここでは、コンソールに'hello'と出力する。
70
+
71
+ * spawn、print関数は、下記でglobalオブジェクトに定義してある。
72
+
73
+ * 下記のmain関数内のJS::Evaluateでこのスクリプトを評価している。
74
+
75
+ */
76
+
77
+ static const char* script = "spawn(() => print(`hello\n`));";
78
+
79
+
80
+
81
+ /**
82
+
83
+ * spawnのC++での実装。
84
+
85
+ * 別スレッドでJS_CallFunctionを実行している。
86
+
87
+ */
88
+
89
+ bool js_spawn(JSContext *cx, unsigned argc, JS::Value *vp)
90
+
91
+ {
92
+
93
+ JS::CallArgs args = CallArgsFromVp(argc, vp);
94
+
95
+ // 念の為、別スレッドで呼ばれてもいいように、GCされないようにする。
96
+
97
+ JS::PersistentRooted<JSObject*> global(cx, JS::CurrentGlobalOrNull(cx));
98
+
99
+ // 念の為、別スレッドで呼ばれてもいいように、GCされないようにする。
100
+
101
+ JS::PersistentRooted<JSFunction*> func(cx, JS_ValueToFunction(cx, args[0]));
102
+
103
+
104
+
105
+ // スレッド生成。
106
+
107
+ auto th = std::thread( [cx, global, func]() {
108
+
109
+ JS::RootedValue rval(cx);
110
+
111
+ if( !JS_CallFunction(cx, global, func, JS::HandleValueArray::empty(), &rval) )
112
+
113
+ cerr << "ERROR: failed to call function at js_spawn()" << endl;
114
+
115
+ });
116
+
117
+ th.join();
118
+
119
+ return true;
120
+
121
+ }
122
+
123
+
124
+
125
+ /**
126
+
127
+ * 文字列をコンソールに出力する。
128
+
129
+ */
130
+
131
+ bool js_print(JSContext *cx, unsigned argc, JS::Value *vp)
132
+
133
+ {
134
+
135
+ JS::CallArgs args = CallArgsFromVp(argc, vp);
136
+
137
+ char* s = JS_EncodeString(cx, args[0].toString());
138
+
139
+ printf("%s", s);
140
+
141
+ JS_free(cx, s);
142
+
143
+ return true;
144
+
145
+ }
146
+
147
+
148
+
149
+ static const size_t heapMaxBytes = 16L * 1024 * 1024;
150
+
151
+ static const size_t nurseryBytes = 4L * 1024 * 1024;
152
+
153
+ static const size_t maxStackSize = 6L * 1024 * 1024;
154
+
155
+ static const size_t stackChunkSize = 8192;
156
+
157
+
158
+
159
+ int main( int argc, char** argv ) {
160
+
161
+
162
+
163
+ JS_Init();
164
+
165
+
166
+
167
+ JSRuntime *rt = JS_NewRuntime(heapMaxBytes, nurseryBytes);
168
+
169
+
170
+
171
+ JS_SetNativeStackQuota(rt, maxStackSize);
172
+
173
+
174
+
175
+ JSContext *cx = JS_NewContext(rt, stackChunkSize);
176
+
177
+
178
+
179
+ {
180
+
181
+ JSAutoRequest ar(cx);
182
+
183
+
184
+
185
+ JSClass globalClass = {
186
+
187
+ "global",
188
+
189
+ JSCLASS_GLOBAL_FLAGS
190
+
191
+ };
192
+
193
+
194
+
195
+ JS::RootedObject global(cx, JS_NewGlobalObject( cx, &globalClass, nullptr, JS::FireOnNewGlobalHook));
196
+
197
+
198
+
199
+ JS::RootedValue rval(cx);
200
+
201
+ {
202
+
203
+ JSAutoCompartment ac(cx, global);
204
+
205
+
206
+
207
+ JSFunctionSpec globalFunctions[] = {
208
+
209
+ JS_FS("print", js_print, 1, 0),
210
+
211
+ JS_FS("spawn", js_spawn, 1, 0),
212
+
213
+ JS_FS_END
214
+
215
+ };
216
+
217
+
218
+
219
+ JS_DefineFunctions(cx, global, globalFunctions);
220
+
221
+
222
+
223
+ JS::CompileOptions opts(cx);
224
+
225
+ opts.setLine(1);
226
+
227
+
228
+
229
+ JS::Evaluate(cx, global, opts, script, strlen(script), &rval);
230
+
231
+ }
232
+
233
+
234
+
235
+ }
236
+
237
+
238
+
239
+ JS_DestroyContext(cx);
240
+
241
+ JS_DestroyRuntime(rt);
242
+
243
+ JS_ShutDown();
244
+
245
+ }
246
+
247
+ ```

1

初心者マーク追加

2016/02/02 05:39

投稿

twinbird
twinbird

スコア12

test CHANGED
File without changes
test CHANGED
File without changes