-
Notifications
You must be signed in to change notification settings - Fork 4.8k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[browser][MT] Make HTTP and WS clients work #87567
[browser][MT] Make HTTP and WS clients work #87567
Conversation
Tagging subscribers to 'arch-wasm': @lewing Issue DetailsIdeas:
Other
|
This comment was marked as spam.
This comment was marked as spam.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The only thing I'd be careful about is assuming that the only synchronization contexts that can be installed on a thread is either nothing or JSSynchronizationContext
.
Also I'm not sure there's any good way to avoid a ton of allocation with the SynchronizationContextExtension methods, but using static
lambdas that don't capture local variables or fields of this
and instead passing extra arguments can decrease some of the allocations. (of course the call to the actual SynchronizationContext.Post(SendOrPostCallback callback, object? state)
method will still need to allocate something - either a state object or a closure. but maybe some of the other allocations can be avoided by carefully constructing the code)
src/libraries/System.Net.WebSockets.Client/src/System.Net.WebSockets.Client.csproj
Outdated
Show resolved
Hide resolved
...System.Net.WebSockets.Client/src/System/Net/WebSockets/BrowserWebSockets/BrowserWebSocket.cs
Outdated
Show resolved
Hide resolved
...eropServices.JavaScript/src/System/Runtime/InteropServices/JavaScript/JSObject.References.cs
Outdated
Show resolved
Hide resolved
...eropServices.JavaScript/src/System/Runtime/InteropServices/JavaScript/JSObject.References.cs
Show resolved
Hide resolved
1ea5b74
to
1bc02d2
Compare
5a0c246
to
5877eda
Compare
/azp run runtime-wasm |
Azure Pipelines successfully started running 1 pipeline(s). |
58a07bf
to
5799250
Compare
/azp run runtime-wasm |
Azure Pipelines successfully started running 1 pipeline(s). |
/azp run runtime-wasm |
Azure Pipelines successfully started running 1 pipeline(s). |
/azp run runtime-wasm |
Azure Pipelines successfully started running 1 pipeline(s). |
#if FEATURE_WASM_THREADS | ||
if (!abortController.IsDisposed) | ||
{ | ||
abortController.SynchronizationContext.Send(static (JSObject _abortController) => | ||
{ | ||
BrowserHttpInterop.AbortRequest(_abortController); | ||
_abortController.Dispose(); | ||
}, abortController); | ||
} | ||
#else | ||
if (!abortController.IsDisposed) | ||
{ | ||
BrowserHttpInterop.AbortRequest(abortController); | ||
abortController.Dispose(); | ||
} | ||
abortController.Dispose(); | ||
#endif |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This should be valid
#if FEATURE_WASM_THREADS | |
if (!abortController.IsDisposed) | |
{ | |
abortController.SynchronizationContext.Send(static (JSObject _abortController) => | |
{ | |
BrowserHttpInterop.AbortRequest(_abortController); | |
_abortController.Dispose(); | |
}, abortController); | |
} | |
#else | |
if (!abortController.IsDisposed) | |
{ | |
BrowserHttpInterop.AbortRequest(abortController); | |
abortController.Dispose(); | |
} | |
abortController.Dispose(); | |
#endif | |
if (!abortController.IsDisposed) | |
{ | |
#if FEATURE_WASM_THREADS | |
abortController.SynchronizationContext.Send(static (JSObject abortController) => | |
{ | |
#else | |
BrowserHttpInterop.AbortRequest(abortController); | |
abortController.Dispose(); | |
#if FEATURE_WASM_THREADS | |
}, abortController); | |
#endif | |
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Are you saying that I should shadow abortController
name in the callback, so that I could have more DRY code ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We can further tweak it in follow-up PRs. I will merge it so that it has time to flow to Blazor over the weekend.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
On the surface LGTM. I'm not super-familiar with the the implementations of these streams, though.
BrowserWebSocket
_thisLock
for locking the state for MT accessFEATURE_WASM_THREADS
to conditionaly wrap the calls withSynchronizationContext.Send
for all calls to JSConnectAsyncCore
andCreateCore
to separate methods.CreateCore
is synchronous and creates the JS proxy. The other one needs to be executed separately, so thatAbort()
beforeawait ConnectAsync()
works as expected. Yielding to main loop.BrowserHttpHandler
WasmFetchResponse.ThisLock
for locking the state for MT accessFEATURE_WASM_THREADS
to conditionaly wrap the calls withSynchronizationContext.Send
for all calls to JSOther
JSSynchronizationContext
possible to install on multiple threadsSynchronizationContextExtension
hidden from API byCompatibilitySuppressions.xml
JSHost.CurrentOrMainJSSynchronizationContext
JSSynchronizationContext
installed on current threadJSObject.SynchronizationContext
WebWorker
hidden from API byCompatibilitySuppressions.xml
JSException
from another thread doesn't have thread affinity and stack trace.Contributes to #85592