Commit b72c73a8 by Romain Courteaud

Speed up mutex.

1 parent 4499150f
......@@ -185,51 +185,22 @@
if (!(this instanceof Mutex)) {
return new Mutex();
}
this._latest_defer = null;
this._latest_promise = null;
};
Mutex.prototype = {
constructor: Mutex,
lock: function lockMutex() {
var previous_defer = this._latest_defer,
current_defer = RSVP.defer(),
queue = new RSVP.Queue();
this._latest_defer = current_defer;
if (previous_defer !== null) {
queue.push(function acquireMutex() {
return previous_defer.promise;
});
lockAndRun: function lockMutexAndRun(callback) {
var previous_promise = this._latest_promise;
if (previous_promise === null) {
this._latest_promise = RSVP.resolve(callback());
} else {
this._latest_promise = this._latest_promise
.always(function () {
return callback();
});
}
// Create a new promise (.then) not cancellable
// to allow external cancellation of the callback
// without breaking the mutex implementation
queue
.fail(current_defer.resolve.bind(current_defer));
return queue
.push(function generateMutexUnlock() {
return function runAndUnlock(callback) {
return ensurePushableQueue(callback)
.push(function releaseMutexAfterSuccess(result) {
current_defer.resolve(result);
return result;
}, function releaseMutexAfterError(error) {
current_defer.resolve(error);
throw error;
});
};
});
},
lockAndRun: function (callback) {
return this.lock()
.push(function executeLockAndRunCallback(runAndUnlock) {
return runAndUnlock(callback);
});
return this._latest_promise;
}
};
......@@ -671,7 +642,9 @@
if (!context.hasOwnProperty(mutex_name)) {
context[mutex_name] = new Mutex();
}
return context[mutex_name].lockAndRun(waitForMethodCallback);
return ensurePushableQueue(context[mutex_name].lockAndRun,
[waitForMethodCallback],
context[mutex_name]);
}
return ensurePushableQueue(callback, argument_list, context);
};
......
......@@ -152,14 +152,17 @@
var mutex = new Mutex(),
counter = 0;
stop();
expect(4);
expect(5);
function assertCounter(value) {
equal(counter, value);
counter += 1;
}
function callback1() {
assertCounter(0);
throw new Error('error in callback1');
return new RSVP.Queue()
.push(function () {
assertCounter(0);
throw new Error('error in callback1');
});
}
function callback2() {
assertCounter(1);
......@@ -179,7 +182,7 @@
})
.push(undefined, function (error) {
equal(error.message, 'error in callback1');
assertCounter(2);
assertCounter(3);
})
.always(function () {
start();
......@@ -196,7 +199,10 @@
counter += 1;
}
function callback1() {
ok(false, 'Should not reach that code');
return new RSVP.Queue()
.push(function () {
ok(false, 'Should not reach that code');
});
}
function callback2() {
assertCounter(1);
......@@ -208,7 +214,7 @@
return RSVP.all([
promise1
.then(function () {
ok(false, 'Should not reach that code');
ok(false, 'Should not reach that code 2');
}, function (error) {
assertCounter(0);
equal(error.message, 'Default Message');
......@@ -288,76 +294,4 @@
});
});
test('lockAndRun only wait for the callback', function () {
var mutex = new Mutex(),
counter = 0;
stop();
expect(4);
function assertCounter(value) {
equal(counter, value);
counter += 1;
}
function callback1() {
assertCounter(0);
return 'callback1 result';
}
function callback2() {
assertCounter(1);
return 'callback2 result';
}
return new RSVP.Queue()
.push(function () {
return RSVP.any([
mutex.lockAndRun(callback1)
.push(function () {
return RSVP.delay(10000);
}),
mutex.lockAndRun(callback2)
]);
})
.push(function (result) {
equal(result, 'callback2 result');
assertCounter(2);
})
.always(function () {
start();
});
});
test('lockAndRun only wait for the error callback', function () {
var mutex = new Mutex(),
counter = 0;
stop();
expect(4);
function assertCounter(value) {
equal(counter, value);
counter += 1;
}
function callback1() {
assertCounter(0);
throw new Error('callback1 error');
}
function callback2() {
assertCounter(1);
return 'callback2 result';
}
return new RSVP.Queue()
.push(function () {
return RSVP.any([
mutex.lockAndRun(callback1)
.push(undefined, function () {
return RSVP.delay(10000);
}),
mutex.lockAndRun(callback2)
]);
})
.push(function (result) {
equal(result, 'callback2 result');
assertCounter(2);
})
.always(function () {
start();
});
});
}(renderJS.Mutex, QUnit));
\ No newline at end of file
Styling with Markdown is supported
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!