Re: Future cancellation

I think that makes lots of sense. Would the destructuring assignment, i.e.
{promise, dispose} = ...
work for functions that return a single result (just a promise) instead of
a result or a disposer?

My main concern about intentionally treating disposal as a non-issue is
that it ensures that it will take a long time for disposal to ever make its
way into common libraries and applications; that is, for disposal to work,
both library authors and consumers need to adopt it. Any pattern that at
least makes it possible to incrementally add disposal in over time, from
the library side and the application side, is optimal - whether you do it
by checking for 'promise.dispose' as a callable, or checking for a
'dispose' second result from functions, or checking to see if a given
promise is branded with some special symbol. This is also why the
cancellation token method is something it worries me to see proposed - it's
a great approach from an engineering perspective, but arguably a large
reason why it worked in .NET is because Microsoft had the ability to make
it the de-facto approach to cancellation and force people to adopt it.

Another option that came to mind is that you could use WeakMap to store the
disposal state of a given future. Any consumer that cares about disposal
can set the flag in the shared weakmap (perhaps through some third party
library that encapsulates the disposal state map) and the producers that
generate futures can check the WeakMap before performing an operation for a
given set of futures. I don't know enough to comment on whether or not this
would be a scalable and optimal solution, but I think it does directly
address the problem of adding cancellation to futures when in many use
cases they will not be of any value. For ocap security you would probably
need to carefully guard access to that weakmap by exposing reads/writes
through privileged functions or something.

-kg


On Tue, Apr 30, 2013 at 10:01 PM, Domenic Denicola <
domenic@domenicdenicola.com> wrote:

>  I think the .NET disposal analogy is a good one. I don’t know how other
> runtimes handle it, but in .NET you would dispose of a resource (perhaps
> representing an in-progress asynchronous operation) by having the handle
> for that resource implement IDisposable, i.e. have a dispose() method. So I
> think if you wanted to do something similar with promises, you’d return a
> disposable handle alongside your promise (i.e. `return { promise, diposable
> }` or simply `{ promise, dispose }`). You can also layer that on top of the
> promise (i.e. `promise.dispose = () => { .. }; return promise;`).****
>
> ** **
>
> *From:* Kevin Gadd [mailto:kevin.gadd@gmail.com]
> *Sent:* Wednesday, May 1, 2013 00:35
> *To:* Domenic Denicola
> *Cc:* Jonas Sicking; Ron Buckton; public-script-coord@w3.org; es-discuss
> *Subject:* Re: Future cancellation****
>
> ** **
>
> To be honest, I haven't yet seen an explanation of why 'I no longer have
> any need for the contents of this future' is not tied to the underlying
> semantics of a future. Where else would it go? I agree with you that
> complicating a primitive in order to support a small subset of use cases is
> undesirable, and it does seem like perhaps end-user subclassing of
> futures/promises addresses all these use cases. But it is troubling to me
> to consistently see real use cases dismissed as somehow unworthy of
> consideration because they do not meet some unspecified semantic bar.****
>
> And to restate some points that have cropped up in the thread multiple
> times so far, since they are relevant to your arguments:****
>
> Future cancellation is not the same as task cancellation; it is different.
> I would agree with any suggestion that using the names 'cancel' or 'abort'
> probably leads people to assume that they are the same. I prefer the term
> 'disposal' but that is perhaps overly .NETty and implies things that do not
> apply to JS.****
>
> Layering disposal onto a promise from the outside is fine, but requires
> that all consumers of an API have prior knowledge of the way the API is
> implemented; that is, the API author has to expose disposal beforehand
> (even if it is not used) and the consumer has to know that it is needed.
> This exposes whether or not disposal is *actually used* by an
> implementation when it should be an implementation detail. Much like how -
> to pick an arbitrary example - finally blocks in a generator should run if
> you enumerate the generator with for-of, it is desirable to have a
> universal way to indicate that a future's value is unneeded by a single
> consumer such that any given API implementer can extend their
> implementation seamlessly to abort operations that are no longer needed.
> This allows significant changes to the backend of an operation (caching,
> batching, etc) without changing the public API. (Note that you can probably
> address this with a Future subclass instead of baking disposal into Future
> itself, or by exposing some sort of public function that you can call on a
> future to indicate that you are done with it and making that function a
> no-op for non-disposable futures. I don't have a strong opinion).
>
> I'm fine with cancellation and progress being nuked from futures for
> conceptual purity; simpler is probably better. But if you're going to kill
> them, you should do it based on sound reasoning, otherwise they're just
> going to keep cropping up again and again because people want them and will
> probably not accept a justification that seems based on a misunderstanding
> of their arguments.****
>
> Given the choice between explicitly not specifying disposal, and
> specifying an 'encouraged way to do it' (i.e. via subclassing), I would
> also lean towards the latter. That is, if you're going to say 'we don't
> need to spec disposal', by demonstrating an incredibly easy way to do it
> via subclassing, you address any arguments that it must be built into the
> language or into DOM futures, and you demonstrate a pattern that is
> expected to work based on the current spec.****
>
> ** **
>
>
> ****
>
> -kg****
>
> ** **
>
> On Tue, Apr 30, 2013 at 9:25 PM, Domenic Denicola <
> domenic@domenicdenicola.com> wrote:****
>
> From: es-discuss-bounces@mozilla.org [mailto:
> es-discuss-bounces@mozilla.org] On Behalf Of Jonas Sicking****
>
>
> > It isn't actually surprising that the same issues arise. ProgressFuture
> basically delivers progress about an "operation" rather than a "result".**
> **
>
> I agree. I think both progress and cancellation (of underlying operations)
> are attractive nuisances. They seem like they fit in well with the model,
> and would be useful for certain use cases. But they are actually very
> different, and not tied to the underling promise semantics at all—which are
> of a first class value representing a promised "result," as you put it, not
> representing an ongoing "operation."
>
> I lean toward not specifying or including them at all. Although you can
> try to stuff them naively into the promise semantics, you end up needing to
> complicate the conceptual model in order to make them behave as you wish.
> As you point out, this is clearly visible with the various combinators. But
> it's also visible in basic semantic questions that arise: e.g. downward
> progress propagation/transformation, or the role of throwing inside a
> progress handler, or upward cancellation progagation/reaction, or downward
> cancellation forking, or the role of rejections in cancellation. You soon
> realize that you're trying to smush in semantics where they don't belong.
>
> In other words, separate abstractions for cancellation or progress,
> unrelated to promises, seem best.****
>
> _______________________________________________
> es-discuss mailing list
> es-discuss@mozilla.org
> https://mail.mozilla.org/listinfo/es-discuss****
>
>  ** **
>

Received on Wednesday, 1 May 2013 05:12:24 UTC