W3C home > Mailing lists > Public > public-script-coord@w3.org > April to June 2013

Re: Future cancellation

From: Ron Buckton <rbuckton@chronicles.org>
Date: Tue, 30 Apr 2013 18:36:18 +0000
To: Alex Russell <slightlyoff@google.com>
CC: es-discuss <es-discuss@mozilla.org>, "public-script-coord@w3.org" <public-script-coord@w3.org>, Tab Atkins Jr. <jackalmage@gmail.com>
Message-ID: <33D2646B20374248B7CAA8F25919AAFC42763483@BY2PRD0111MB494.prod.exchangelabs.com>

Thank you for the feedback.  Ive also added two more gists:

4. Cancellation using CancellationTokenSource: https://gist.github.com/rbuckton/5490373
5. Cancellation using CancelableFuture subclass: https://gist.github.com/rbuckton/5490482

Each one of these is an attempt to find out exactly what does and doesnt work with various mechanisms for cancellation that have been discussed on these lists as well as in various libraries.

In [1] I added the synchronous flag as a way to ensure that the Future that is used for cancellation can resolve and have its resolve callbacks run in time. Its not exactly necessary but there are some cases where not being able to cancel synchronously could bite a developer:

function someAsync(cancelFuture) {
  return new Future(function (resolver) {
    var handle = setImmediate(function () {  });
    cancelFuture.done(function () { clearImmediate(handle); });

var { token, cancel } = createCanceler();
var f = someAsync(token);

Due to asynchronous resolution, even though cancel() is called synchronously it will be scheduled *after* the setImmediate call.

[2] was based on a side discussion around cancellation and similarities to revocable Proxies.

[3] was based on providing a simple means of cancellation, but I agree that there is a danger that a Future that is referenced by multiple consumers could be canceled by any consumer.

[4] is inspired by cooperative cancellation of Tasks in .NET. Ive used this quite often and found it to be a powerful cancellation mechanism. It has the advantage of being very explicit about where responsibilities lie as part of cancellation and reducing pollution of the Future API, but it does add additional complexity around setup. Im personally in favor of this approach, though not so fond of the name of types.  [1] is partially based on this approach as well, except that CTS cancels synchronously and can automatically reject a Future.

[5] is a possible approach (albeit a nave implementation) of cancellation via a subclass. In its current incarnation it suffers from the same issues a [1] and [2], but can be mitigated by having it directly call the resolvers resolve algorithm with the synchronous flag set. It also gets lost when using Future.any, etc.

My intent currently is not to advocate any of these approaches. Rather; Im trying to catalogue each approach as Ive come across them specifically to gather this kind of feedback.

Best regards,

Sent from Windows Mail

From: Alex Russell
Sent: Tuesday, April 30, 2013 2:54 AM
To: Ron Buckton
Cc: es-discuss, public-script-coord@w3.org, Tab Atkins Jr.

These are horribly confused -- and likely foot-gun -- designs.

First, synchronous resolution needs some justification. I don't understand why you've added it in the first design. The question of "does the Resolver know it is resolved?" is entirely independent of the visibility of that resolution to the outside world. I don't think this flag even makes sense.

In terms of blessing one or another static method for generating the cancellable tuple (as you do in your first two designs), why does it have to be in the design at this point? The current design in DOM provides a small contract to keep us from fighting over how to distinguish cancellation from other error values (the side-contract everyone would need to re-create at great expense), but purposefully avoids doing this for the sake of simplicitly. I don't get why you're trying to expand this contract in the core spec. Just subclass. Should it become so common, we can revisit this later.

Lastly, your final design is irretrievably broken in a way the first two aren't: it vends to anyone who has a handle to the Future the capability to reject it.

The DOM design has studiously avoided this class of fatal design errors so far. It's the key reason why Resolvers and Futures are separate objects. No such design will fly in this group.


On Tuesday, April 30, 2013, Ron Buckton wrote:
Ive created separate gists for three different ways that I am currently investigating as a means to support the cancellation of a Future. These can be found here:

1.       Cancellation using Future: https://gist.github.com/rbuckton/5486149

2.       Cancellation using Future.cancelable: https://gist.github.com/rbuckton/5484591

3.       Cancellation using Future#cancel: https://gist.github.com/rbuckton/5484478

Each has a list of some of the benefits and issues Ive seen while experimenting with each approach, as well as possible changes to the various APIs or algorithms for Future to make each happen.

In general, cancellation of a Future can be beneficial in a number of cases.  One example is the case where you are requesting a resource from a remote server using XHR. If the request was being made to fetch a page of data, and the user opted to move to the next page before the current page completed loading, it no longer becomes necessary to continue fetching the remote resource. In addition, it is no longer necessary to handle any additional computation or transformation logic that would have resulted from the successful completion of the fetch operation. Having the ability to cancel the request allows an application to quickly release resources that it no longer needs.

It is also useful to be able to handle the cancelation of a long running task that might be executing in a Worker. In this case, cleanup logic that is part of cancelation would request the worker to close, ending the current operation and releasing resources.

Both of the above examples are indicative of cancelling the root of an operation, but there are also circumstances where you might want to cancel a chained Future and any Future chained from it, without canceling the root. In the previous example regarding paged data, I might wish to allow the fetch operation to complete so that I could cache the data for quick retrieval, but would only want to cancel any possible UI updates that might occur in a chained Future.

Im interested to hear what others think with respect to properly handling cancellation with Futures.

Received on Tuesday, 30 April 2013 18:37:48 UTC

This archive was generated by hypermail 2.4.0 : Friday, 17 January 2020 17:14:13 UTC