@@ -64,12 +64,12 @@ int emscripten_proxy_sync(em_proxying_queue* q,
64
64
void* arg);
65
65
66
66
// Enqueue `func` on the given queue and thread and wait for it to be executed
67
- // and for the task to be marked finished with `emscripten_proxying_finish`
68
- // before returning. `func` need not call `emscripten_proxying_finish ` itself;
69
- // it could instead store the context pointer and call
70
- // `emscripten_proxying_finish` at an arbitrary later time. Returns 1 if the
71
- // task was successfully completed and 0 otherwise, including if the target
72
- // thread is canceled or exits before the work is completed.
67
+ // and for the task to be marked finished with `emscripten_proxy_finish` before
68
+ // returning. `func` need not call `emscripten_proxy_finish ` itself; it could
69
+ // instead store the context pointer and call `emscripten_proxy_finish` at an
70
+ // arbitrary later time. Returns 1 if the task was successfully completed and 0
71
+ // otherwise, including if the target thread is canceled or exits before the
72
+ // work is completed.
73
73
int emscripten_proxy_sync_with_ctx (em_proxying_queue* q,
74
74
pthread_t target_thread,
75
75
void (*func)(em_proxying_ctx*, void *),
@@ -88,6 +88,20 @@ int emscripten_proxy_callback(em_proxying_queue* q,
88
88
void (*cancel)(void *),
89
89
void* arg);
90
90
91
+ // Enqueue `func` on the given queue and thread. Once (and if) it finishes the
92
+ // task by calling `emscripten_proxy_finish` on the given `em_proxying_ctx`, it
93
+ // will asynchronously proxy `callback` back to the current thread on the same
94
+ // queue, or if the target thread dies before the work can be completed,
95
+ // `cancel` will be proxied back instead. All three function will receive the
96
+ // same argument, `arg`. Returns 1 if `func` was successfully enqueued and the
97
+ // target thread notified or 0 otherwise.
98
+ int emscripten_proxy_callback_with_ctx (em_proxying_queue* q,
99
+ pthread_t target_thread,
100
+ void (*func)(em_proxying_ctx*, void *),
101
+ void (*callback)(void *),
102
+ void (*cancel)(void *),
103
+ void* arg);
104
+
91
105
#ifdef __cplusplus
92
106
} // extern "C"
93
107
@@ -103,6 +117,18 @@ namespace emscripten {
103
117
104
118
// A thin C++ wrapper around the underlying C API.
105
119
class ProxyingQueue {
120
+ public:
121
+ // Simple wrapper around `em_proxying_ctx*` providing a `finish` method as an
122
+ // alternative to `emscripten_proxy_finish`.
123
+ struct ProxyingCtx {
124
+ em_proxying_ctx* ctx;
125
+
126
+ ProxyingCtx () = default ;
127
+ ProxyingCtx (em_proxying_ctx* ctx) : ctx(ctx) {}
128
+ void finish () { emscripten_proxy_finish (ctx); }
129
+ };
130
+
131
+ private:
106
132
static void runAndFree (void * arg) {
107
133
auto * f = (std::function<void ()>*)arg;
108
134
(*f)();
@@ -150,6 +176,37 @@ class ProxyingQueue {
150
176
delete info;
151
177
}
152
178
179
+ struct CallbackWithCtxFuncs {
180
+ std::function<void (ProxyingCtx)> func;
181
+ std::function<void ()> callback;
182
+ std::function<void ()> cancel;
183
+
184
+ CallbackWithCtxFuncs (std::function<void (ProxyingCtx)>&& func,
185
+ std::function<void ()>&& callback,
186
+ std::function<void ()>&& cancel)
187
+ : func(std::move(func)), callback(std::move(callback)),
188
+ cancel (std::move(cancel)) {}
189
+ };
190
+
191
+ static void runFuncWithCtx (em_proxying_ctx* ctx, void * arg) {
192
+ auto * info = (CallbackWithCtxFuncs*)arg;
193
+ info->func (ProxyingCtx{ctx});
194
+ }
195
+
196
+ static void runCallbackWithCtx (void * arg) {
197
+ auto * info = (CallbackWithCtxFuncs*)arg;
198
+ info->callback ();
199
+ delete info;
200
+ }
201
+
202
+ static void runCancelWithCtx (void * arg) {
203
+ auto * info = (CallbackWithCtxFuncs*)arg;
204
+ if (info->cancel ) {
205
+ info->cancel ();
206
+ }
207
+ delete info;
208
+ }
209
+
153
210
public:
154
211
em_proxying_queue* queue = em_proxying_queue_create();
155
212
@@ -179,16 +236,6 @@ class ProxyingQueue {
179
236
}
180
237
}
181
238
182
- // Simple wrapper around `em_proxying_ctx*` providing a `finish` method as an
183
- // alternative to `emscripten_proxy_finish`.
184
- struct ProxyingCtx {
185
- em_proxying_ctx* ctx;
186
-
187
- ProxyingCtx () = default ;
188
- ProxyingCtx (em_proxying_ctx* ctx) : ctx(ctx) {}
189
- void finish () { emscripten_proxy_finish (ctx); }
190
- };
191
-
192
239
void execute () { emscripten_proxy_execute_queue (queue); }
193
240
194
241
// Return true if the work was successfully enqueued and false otherwise.
@@ -225,6 +272,24 @@ class ProxyingQueue {
225
272
}
226
273
return true ;
227
274
}
275
+
276
+ bool proxyCallbackWithCtx (pthread_t target,
277
+ std::function<void (ProxyingCtx)>&& func,
278
+ std::function<void()>&& callback,
279
+ std::function<void()>&& cancel) {
280
+ CallbackWithCtxFuncs* info = new CallbackWithCtxFuncs (
281
+ std::move (func), std::move (callback), std::move (cancel));
282
+ if (!emscripten_proxy_callback_with_ctx (queue,
283
+ target,
284
+ runFuncWithCtx,
285
+ runCallbackWithCtx,
286
+ runCancelWithCtx,
287
+ info)) {
288
+ delete info;
289
+ return false ;
290
+ }
291
+ return true ;
292
+ }
228
293
};
229
294
230
295
} // namespace emscripten
0 commit comments