Hi,

Le 30 sept. 2016 07:51, "Jean-Philippe André" <j...@videolan.org> a écrit :
> Here's a question about promise chaining. C being what it is, it's harder
> to define a series like p.then().then() than it is in JS. And I can't find
> any good example in EFL code.
>
> Let's consider an abstract chain that I'll define as "download, unzip,
> show". (eg. download a zip file, unzip it and set the file on an image
> object).
>
>
> All of these are async, we don't care about the result of show. I don't
> understand how the chain should be written:
>
> main_func(url) {
>   Efl_Future *f1 = download_url(url);
>   Efl_Future *f2 = efl_future_then(f1, _down_cb, ...,  NULL);
>   efl_future_then(f2, _unzip_cb, ..., image);
> }
>
> // So far I think we're ok
>
> void _down_cb(null, event) {
>    Efl_Promise *next = event->info->next;
>    Efl_Future *f3 = _async_unzip(event->infodata);
>    efl_future_then(f3, _unzip_cb2, .., next);
> }
>
> // I'm already getting confused with next, f2 and f3. Something is odd.

Yes, that's why there is some function (I don't have the code at end), to
feed a future into a promise. This connection take care of propagating the
value to the next promise. It avoid having to setup your own callback to do
so as you did in this example.

> void _unzip_cb(data, event) {
>    Image *image = data;
>    show(image);
> }
>
> void _unzip_cb2(data, event) {
>    Efl_Promise *p2 = data;
>    efl_promise_value_set(p3, NULL, NULL); // --> calls unzip_cb
> }
>
>
> So my questions:
> 1. Is this above code correct?

Yes.

> 2. (How) are we ensuring that the chain eventually resolves?

You mean, that if you don't set anything on the next promise, nothing will
happen ? There is nothing there we can do I think, as everything being
asynchronous, we can't know if there is a good reason that the value hasn't
been set after we leave the callback.

Possible hack for this is to unref the next promise. If the callback hasn't
refed it nor set a failure/value, it will trigger an error and trigger a
failure on the next future. Doable, but not sure if the value.do you think
it's worth it ?

> 3. Couldn't this be made in a simpler way? unzip_cb2 is really just an
> automatic resolve of another promise/future.

Yes, as said before, chaining imply we should be able to set a future as a
value on a promise.

> In unzip_cb, if I ignore "next", f2 will never come to completion.
>
> So here's a proposal:
>
> 1. Get rid of info->next. Instead:
>
> Efl_Promise *p2 = efl_promise_next(event->object);
>
> That way, EFL knows that the developer has not ignored the promise. The
> developer must then call efl_promise_value/error_set at some point, sync
or
> async.

This can not work.every set of callback need a different next promise
otherwise only one of them can really use it. For the same reason, multiple
st if callback are useful, we need to associate multiple next promise.

> If the callback doesn't call efl_promise_next, EFL knows that the "next"
> promise will never come to completion, ever. In that case, EFL
> automatically calls efl_promise_value_set(next, NULL, NULL) to keep
walking
> the chain. (Another idea is to instead cancel it).

See above proposition to do the same and still have multiple callback.

> According to [ https://promisesaplus.com/ ], if onResolve is not a
function
> (success_cb is NULL), then p2 is fullfilled with the same value as p1. So
I
> guess we would just call _unzip_cb directly in the above example.

Yes, that's something I plan to handle, setting null function well just
propagate the value/error/process down the chain.

> Without efl_promise_next() the callback must always handle "next". Failure
> to do so will break all chains, and leak. The value of "next" can be set
> inside _efl_loop_future_success.

Yes, but it's kind of a false problem anyway. If you set expect a future
and never get it triggered and you're the one who is in charge of the
promise, you have maximum 2 places where you may have forgotten to set a
value/trigger a failure. We can improve the detection as proposed above,
but I don't think it's a real problem.

> 2. (raster's idea) Get rid of event->info
>
> Similarly, use efl_promise_value_get() instead of event->info->value. That
> way we can implement stealing with efl_promise_value_steal(&val,
&freefunc)
> and keep the symmetry with value_get().

I am not a fan of area stealing value. It may create slight problem with
multiple callback and other user have to be aware of what you're doing
(order if registering callback also matters in that case). So I would think
that if you want the ability to steal a value, we should actually have a
different efl_future_steal that allow only one callback and prevent any
other efl_future_then to be registered (and trigger an error if any are).
Which means, that value get is pretty much unnecessary. We can have it, as
it solve the issue we have by reusing efl_event_cb (but maybe we should try
to solve that instead of going around it).

> In that case, efl_ref(promise) can be used to keep a value alive for as
> long as you want. It's just a storage object. [if not eo, then
promise_ref,
> whatever]
> Any weak ref by efl_promise_use probably needs to be reset to NULL after
> the success/fail callback.

That is array perfectly doable and the expected behavior today with
efl_promise/efl_future (the c++ binding use that on future).

> 3. multiple then, race, all order of operations
> WIth steal, and any kind of cleanup callback, the order of operations is
> crucial. Is it well defined? Example:
>
> f1 = function();
> efl_future_then(f1, _then1, ...);
> efl_future_then(f1, _then2, ...);
> efl_future_then(f1, _then3, ...);
> // then1, then2, then3 MUST be called in this order (I think)
>
> f2 = function();
> efl_future_then(efl_future_all(f1, f2), _then4);
> efl_future_then(f2, _then5, ...);
> // will it be _then4, _then5 or _then5, _then4?
> // same question for race
> // I believe the implementation is fine here, but not many docs/tests/uses
> :(

Yup, you can see the problem.

> Thoughts?
> Is the above OK or completely off track?

I think there are easier way to solve this problem without breaking
everything !

> PS: Sorry this mail became longer than I thought at first :-/

Raster bad influence I guess ! :-)

Cedric

> --
> Jean-Philippe André
>
------------------------------------------------------------------------------
> _______________________________________________
> enlightenment-devel mailing list
> enlightenment-devel@lists.sourceforge.net
> https://lists.sourceforge.net/lists/listinfo/enlightenment-devel
------------------------------------------------------------------------------
Check out the vibrant tech community on one of the world's most 
engaging tech sites, SlashDot.org! http://sdm.link/slashdot
_______________________________________________
enlightenment-devel mailing list
enlightenment-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/enlightenment-devel

Reply via email to