Open kakukogou opened 8 years ago
Don't use SharedArrayBuffer. We want to avoid the possibility of races. Instead make mapDataInto neuter buffer
so that it can no longer be written into.
Like the post => http://robert.ocallahan.org/2013/07/avoiding-copies-in-web-apis.html
Neutering indeed prevents data racing but how will the caller get the buffer
back?
The neutering operation defined in the HTML spec is a non-reversible operation:
Transferring is an irreversible and non-idempotent operation. Once an object has been transferred, it cannot be transferred, or indeed used, again.
And, It seems that there is no definition of "un-neutering". (Correct me if I was wrong.)
Moreover, the buffer
argument might be the asm.js application's run-time heap and if the mapDataInto()
neuters it, the application will then lose its heap...?
Why would you want to get the buffer back? It's an output buffer.
This is indeed a problem for asm.js. I don't know what the current thinking is about how to make this fit with asm.js.
Why would you want to get the buffer back? It's an output buffer.
Just because it's an output buffer, so the caller need to access it later. For example:
var bitmap = createImageBitmap(......);
var format = bitmap.findOptimalFormat();
var length = bitmap.mappedDataLength(format);
var buffer = new ArrayBuffer(length);
var p = bitmap.mapDataInto(format, buffer, 0, length); // If the _buffer_ is neutered here.
p.then(function() {
var view = new Int32TypedArray(buffer); // This will be a bad operation since the length of _buffer_ now is 0.
// No way to access the data in the _buffer_.
});
Do I misunderstand anything?
Is the application going to read from it later, or write to it later as well?
If the application wants to write into it later, then mapDataInto needs to have the semantics of making a copy.
Is the application going to read from it later, or write to it later as well?
Both read and write are possible.
If the application wants to write into it later, then mapDataInto needs to have the semantics of making a copy.
My implementation now does coping the ImageBitmap's data into the given buffer. (Maybe the bugzilla discussion is related to this topic.)
But, my point is that if the buffer is already neutered by the mapDataInto()
, then, no matter the buffer is mapping or coping the ImageBitmap's data, it is never accessible again in the latter JavaScript code. Isn't it?
Right.
Actually I was a bit confused above, sorry. mapDataInto is defined to copy the ImageBitmap contents into the array buffer. Therefore, changes to the array buffer must not affect the ImageBitmap. There is no race.
But the racing happens at another point. It happens if developers call the mapDataInto()
with a buffer and then write the buffer immediately after the mapDataInto()
function call, in stead of waiting for the promise to be resolved/rejected. In this situation, both the mapDataInto()
native implementation and the JavaScript code might write into the buffer at the same time. (Please refer to the sample code in the top post of this issue.)
Looks like neutering (without un-neutering mechanism) is not a solution?
Then the mapping part of mapDataInto would have to be synchronous. It could happen either during the mapDataInto call or at the moment the promise resolves. The latter would give you more optimization opportunities (e.g. do format conversion async and then map or copy the changed data into place at the end).
@jrmuizel mentioned that the current design of
mapDataIntp()
method might lead to data racing code such as:@jrmuizel proposes that changing to use
SharedArrayBuffer
so that the API itself explicitly says the data racing can happen.Note that the
mapDataInto()
is designed to cooperate with ASM.js applications so that the API can fill data into ASM.js' run-time heap. So, if we change to useSharedArrayBuffer
, the ASM.js application should also be compiled so that its run-time buffer is aSharedArrayBuffer
too.Personally, I think this is a good suggestion. @rocallahan, @anssiko and @smaug----, may I have your comments on this issue?