Bug 1077354 - Extending PromiseWorker to simplify transfering values r=froydnj

This commit is contained in:
David Rajchenbach-Teller 2014-11-20 12:40:08 +01:00
parent ccd5aab92b
commit 9aa803239e
2 changed files with 62 additions and 1 deletions

View File

@ -244,7 +244,10 @@ this.BasePromiseWorker.prototype = {
* @param {string} fun The name of the function to call.
* @param {Array} args The arguments to pass to `fun`. If any
* of the arguments is a Promise, it is resolved before posting the
* message. By convention, the last argument may be an object `options`
* message. If any of the arguments needs to be transfered instead
* of copied, this may be specified by making the argument an instance
* of `BasePromiseWorker.Meta` or by using the `transfers` argument.
* By convention, the last argument may be an object `options`
* with some of the following fields:
* - {number|null} outExecutionDuration A parameter to be filled with the
* duration of the off main thread execution for this call.
@ -264,6 +267,22 @@ this.BasePromiseWorker.prototype = {
}
if (transfers) {
transfers = yield Promise.resolve(Promise.all(transfers));
} else {
transfers = [];
}
if (args) {
// Extract `Meta` data
args = args.map(arg => {
if (arg instanceof BasePromiseWorker.Meta) {
if (arg.meta && "transfers" in arg.meta) {
transfers.push(...arg.meta.transfers);
}
return arg.data;
} else {
return arg;
}
});
}
let id = ++this._id;
@ -352,3 +371,21 @@ this.BasePromiseWorker.prototype = {
function WorkerError(data) {
this.data = data;
};
/**
* A constructor used to send data to the worker thread while
* with special treatment (e.g. transmitting data instead of
* copying it).
*
* @param {object=} data The data to send to the caller thread.
* @param {object=} meta Additional instructions, as an object
* that may contain the following fields:
* - {Array} transfers An array of objects that should be transferred
* instead of being copied.
*
* @constructor
*/
this.BasePromiseWorker.Meta = function(data, meta) {
this.data = data;
this.meta = meta;
};

View File

@ -60,6 +60,7 @@ add_task(function* test_rejected_promise_args() {
}
});
// Test that we can transfer to the worker using argument `transfer`
add_task(function* test_transfer_args() {
let array = new Uint8Array(4);
for (let i = 0; i < 4; ++i) {
@ -80,6 +81,29 @@ add_task(function* test_transfer_args() {
}
});
// Test that we can transfer to the worker using an instance of `Meta`
add_task(function* test_transfer_with_meta() {
let array = new Uint8Array(4);
for (let i = 0; i < 4; ++i) {
array[i] = i;
}
Assert.equal(array.buffer.byteLength, 4, "The buffer is not neutered yet");
let message = new BasePromiseWorker.Meta(array, {transfers: [array.buffer]});
let result = (yield worker.post("bounce", [message]))[0];
// Check that the buffer has been sent
Assert.equal(array.buffer.byteLength, 0, "The buffer has been neutered");
// Check that the result is correct
Assert.equal(result.toString(), "[object Uint8Array]", "The result appears to be a Typed Array");
Assert.equal(result.byteLength, 4, "The result has the right size");
for (let i = 0; i < 4; ++i) {
Assert.equal(result[i], i);
}
});
function run_test() {
run_next_test();
}