w3c / mediacapture-worker

MediaStream with worker
Other
9 stars 12 forks source link

Use SharedArrayBuffer as the parameter type of mapDataInto() to indicate that data racing might happen. #45

Open kakukogou opened 8 years ago

kakukogou commented 8 years ago

@jrmuizel mentioned that the current design of mapDataIntp() method might lead to data racing code such as:

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);  <----.
                                                             | 
var view = new Int32TypedArray(buffer);                      | Data racing.
view[0] = 100;  <--------------------------------------------'

@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 use SharedArrayBuffer, the ASM.js application should also be compiled so that its run-time buffer is a SharedArrayBuffer too.

Personally, I think this is a good suggestion. @rocallahan, @anssiko and @smaug----, may I have your comments on this issue?

rocallahan commented 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.

ChiahungTai commented 8 years ago

Like the post => http://robert.ocallahan.org/2013/07/avoiding-copies-in-web-apis.html

kakukogou commented 8 years ago

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...?

rocallahan commented 8 years ago

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.

kakukogou commented 8 years ago

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?

rocallahan commented 8 years ago

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.

kakukogou commented 8 years ago

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?

rocallahan commented 8 years ago

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.

kakukogou commented 8 years ago

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?

rocallahan commented 8 years ago

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).