Skip to content

Add canvas transfer API for next thread#26464

Open
stevennyman wants to merge 1 commit intoemscripten-core:mainfrom
stevennyman:std-thread-next-thread-transferred-canvases
Open

Add canvas transfer API for next thread#26464
stevennyman wants to merge 1 commit intoemscripten-core:mainfrom
stevennyman:std-thread-next-thread-transferred-canvases

Conversation

@stevennyman
Copy link
Copy Markdown

@stevennyman stevennyman commented Mar 17, 2026

Useful for thread creation APIs such as std::thread or boost::thread that do not let you pass a pthread_attr_t and therefore cannot use emscripten_pthread_attr_settransferredcanvases() for transferring canvases. Fixes #10307.

The APIs added to <emscripten/threading.h> are emscripten_set_next_thread_transferredcanvases(const char* str) and emscripten_get_next_thread_transferredcanvases(const char** str). This PR also adds a test case and documentation.

(Note: I worked with an LLM while preparing this PR and made adjustments as needed.)

@stevennyman
Copy link
Copy Markdown
Author

Following up since it's been some time

@kripken
Copy link
Copy Markdown
Member

kripken commented Mar 27, 2026

Seems reasonable to me. @sbc100 @juj any thoughts?

Copy link
Copy Markdown
Collaborator

@sbc100 sbc100 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Seems a little clunky.. but maybe there not a more elegant way to do this?

How about providing a way to transfer canvas after thread creation?

@stevennyman stevennyman force-pushed the std-thread-next-thread-transferred-canvases branch 2 times, most recently from 226f855 to ad65e2d Compare March 27, 2026 19:13
Useful for thread creation APIs that do not let you pass a pthread_attr_t. Fixes emscripten-core#10307.
@stevennyman stevennyman force-pushed the std-thread-next-thread-transferred-canvases branch from ad65e2d to 8a439eb Compare March 27, 2026 23:07
@stevennyman
Copy link
Copy Markdown
Author

Seems a little clunky.. but maybe there not a more elegant way to do this?

How about providing a way to transfer canvas after thread creation?

Based on #10307 (comment) it appears that it might not be straightforward to implement canvas transfer methods after thread creation unless there have been changes since that comment was made.

@stevennyman stevennyman force-pushed the std-thread-next-thread-transferred-canvases branch 2 times, most recently from 73a90db to 8a439eb Compare March 27, 2026 23:41
@stevennyman
Copy link
Copy Markdown
Author

CI failures seem to be for unused variables in parts of the codebase not modified by this PR. I'm not sure why.

@juj
Copy link
Copy Markdown
Collaborator

juj commented Mar 30, 2026

Hmm, does this actually work?

Remember: all thread creation are proxied to the main thread under pthreads. This is (among other things) because there are no nested Worker/thread creation.

So, if main thread (or some other thread) is calling

emscripten_set_next_thread_transferredcanvases("mycanvas");
std::thread thr(thread_start); // intended to get 'mycanvas'

and another thread happens to race, to also create a thread

std::thread thr(another_thread_start);

then because the thread creation is proxied, and pthread cancellation points (the points at which the proxying system checks if another thread has a pending proxy request) can occur inside std::thread ctor (say, if its internal implementation reads I/O, or calls any shared state/mutex function), it could happen that it is actually another_thread_start that will be the next thread to be created, and receive the transferred canvas, and not the thread_start thread.

The original transferred offscreen canvases mechanism was intended to help portability without code changes, in scenarios where the exact same code should run in the ported codebase. (when users cannot afford to change code)

Here in this PR, this proposed new function probably does not fall under those constraints? So solving this by code changes to the user project would be ok?

In juj/wasm_webgpu, I created a "userland" mechanism to transfer a canvas to a thread: https://github.com/juj/wasm_webgpu/blob/8063d5373eeefac5e627c6830681e71acc4a9f35/samples/offscreen_canvas/offscreen_canvas_pthread.c#L37-L56 . I think this is a more natural "web-native" way to pass a canvas to a pthread (or a Wasm Worker).

That code should work for std::thread with the std::thread::native_handle() functionality.

The idea there is to first create the thread, and then have a separate API to pass the OffscreenCanvas to that already created thread.

If you want to integrate with the existing WebGL mechanism, then a bit of extra JS library code will be needed to inject the transfered canvas to GL.offscreenCanvases map, though should be straightforward.

The JS side code for the above sample lives at https://github.com/juj/wasm_webgpu/blob/8063d5373eeefac5e627c6830681e71acc4a9f35/lib/lib_webgpu.js#L2604-L2711 to give an idea.

Can you give the above a peek - would that solve the usage here instead?

@stevennyman
Copy link
Copy Markdown
Author

Thanks @juj for the pointers and the examples. The idea of creating JS functions to use from C and setting up a pthread by first pointing it to a dummy function while sending the canvas sounds like a reasonable solution and it seems like it should theoretically be somewhat straightforward to implement as well; it seems like hopefully the other thread would pick it up if I set GL.currentContext. I'll look into this.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

emscripten_pthread_attr_settransferredcanvases with std::thread

4 participants