On Mon, 27 Jun 2016 15:55:02 -0700 Cedric BAIL <cedric.b...@free.fr> said:

> On Sat, Jun 25, 2016 at 7:12 AM, Carsten Haitzler <ras...@rasterman.com>
> wrote:
> > On Sat, 25 Jun 2016 10:28:37 -0300 Felipe Magno de Almeida
> > <felipe.m.alme...@gmail.com> said:
> > i think a big difference is our view of promises. to me a promise is an
> > OBJECT that REPRESENTS the async action (and then is responsible for
> > calling the correct callbacks and for storing the value until all such
> > callbacks are called etc. etc.). you (and cedric) keep referring to
> > promises as async values. at least in every language binding they are
> > OBJECTS. they have methods on them (p.then(), and to cancel p.cancel() for
> > starters).
> 
> This pretty much explain all disagreement and missunderstanding here.
> I haven't realized until you said so that you expected to use
> "promise" in that way. This match closely what you have done with
> "vpath" in fact and not at all what is understood to be a promise
> (a.k.a. a container for a future value) in most language. I am not a
> fan at all of inventing our own concept that doesn't match the rest of
> the world, but my strongest reserve is that I think this lead to more
> problem than it solves.

ummm errr.... at least eina_promise was exactly that - an object you can set up
then's, progress cb's, store a value AND call a cancel method on. that's
precisely the implementation and it looks like an object to me. the moment you
are doing things like

p.then(x)
p.else(x)
p.cancel()

etc. - that's an object, not a value. a promise represents an async action, NOT
a value, because it has cancel(). you CANNOT cancel a value. you CAN cancel an
ACTION. and i'll repeat using promises to replace job and timer objects... is
making a promise be an object. you have to be able to cancel jobs and timeouts
and so... it's an object. in js and c++ promises (futures) are OBJECTS with
methods you call on them. our promises already don't match - we have cancel.
the others do not. we have to accept the fact our promises wont totally match.
otherwise make them match to the lowest common denominator in all languages.
cancelling is not possible in c++ or in js (es 6). but if you want to make
our promises match every language then promises are useless for efl. without
being able to cancel then then i say dump them.

> First the problem that this does solve. As there is no owner of the
> write side of the promise, only internal use, you do not have this
> lifecycle problem at all and as you also advocate for only one
> listener, it means you also avoid the problem of having to keep the n
> user of it happy. This solve the lifecycle issue I have been
> discribing since the start with using eo for this purpose.

even if you have multiple then's - the promise stays alive until all then's are
executed. it's an extension of the same principle. still no lifecycle issue
UNLESS you insist on the promise being around after all then's (or else's)
then... ref it one more time and presto. :) it stays around. that's why i don't
see a lifecycle issue. it's  simple. 99% of uses will be a single then or else
callm and even if it's multiple it's still simple.

now the WRITE side does need to track lifetime of the promise. because the code
being given the promise (or future) can cancel it or delete it (deletion should
cancel anyway), then writer HAS to track this to know when to stop doing their
work.

this is where splitting into promise writer and promise (it's better to ca them
writer than owner). if the promise obj is deleted it can let the writer know
and whoever is doing the async promise work can poll for this every "step" and
stop doing work if the promise is gone. throw away existing work and abort.

> The most important problem I see. If the operation is to be done from
> the inside of the promise, using it in object like efl.canvas.image,
> means that either you get efl.canvas.image to have a priviledge access
> to the internal of the promise, so that you can force its resolve on
> demand, or you need to implement a wait on most promise with the risk
> of ending in deadlock. That and the fact it doesn't match what other
> language are providing, are in my opinion the biggest problem I see
> with this idea.

well c++ expects a wait... :) it doesn't think of a mainloop. it seemingly
thinks that "conceptually" there is some thread or child process doing the work
and you can sit on a blocking "read" for the result. that this is an expected
design pattern when using promises/futures.

> Also in most case where we use promise at the moment they are
> literrally under the control of another object as they are just
> delivering a result for an existing object. The only case where we

but this pattern is killed with jobs and timeouts.

> could use this behavior at some advantage is for Eio promise, but even
> then I am not to sure of the outcome. We could in that case extend
> signals for filtering and sorting on the promise (progress should be
> part of the default property of a promise as this follow ES6), but
> this become something bindings have to care about. This is going to be
> tricky when we are chaining promise. What happen to this events once
> put into an all/race/chain promise ? Whatever extention we use on a
> promise, it will be tricky to have them available outside of C.

each language has a slightly different idea of promises. lua doesn't even have
any concept of them. and no - coroutines are nothing like a promise/future.
anyway - if you want promises that totally look native, they have to be the
lowest common denominator of all languages, and that makes them useless for
efl. they are not worth the effort or complexity. IF you accept that our
promises are extended and can do more and work in specific ways, then they can
work, but then... they don't match native promises. cancel. need i say more.
neither c++ nor js offers cancellation.

> On the other hand sticking with a more classic promise/future
> container concept, we can avoid the problematic exposition of wait and
> the risk of a deadlock as any object that would require to resolve a
> promise could force it internally. It also means that instead of
> having a one promise that does everything like vpath, you go by
> chaining them. A first one that resolve an uri to an Eina.File and in
> the then of that promise you set the file on the destination object.
> This means that the destination object doesn't need to resolve a file
> download before it is done and you have no dead lock.
> 
> Now I can see that extending the promise/write side could be useful in
> some case and not risky as it is hidden from bindings completely as
> they only needs to actually expose a future. So when you actually

actually... no. bindings have to expose the write side... BECAUSE it has to be
possible to inherit a class with a method that returns a promise and change the
implementation of that function  e.g. create a promise of your own in js or c++
and return it.

> extend a promise/write side it stay actually hidden from the binding
> and doesn't create any trouble there. Thinking more about it the main
> issue we were facing with using Eo and its lifecycle is that we wanted
> to save on performance by merging the promise and future together.

well i was just thinking it's simpler not to have 2. in c++ split them into 2 c+
+ objects but they map to the same eo object behind in c.

but to have one object, then we need a way for the writer to know the promise
has been deleted by the reader/watcher side. one way would be to hook a DEL
event cb on the promise, and this executes in the same context as the
reader/watcher. this can then message/flag/whatever the writer thread (if it's
a thread) or blob of code, so the next time it "checks" for the promise
existence, it knows it's gone. splitting into 2 objects means we can have the
eo promise writer object handle this and just have a method on it the writer
can call to check for a missing promise "watcher" object. but if this is dont
in another thread we have a promise being created in thread a and deleted in
thread b. is this good? well - it means we have to be careful. if you have the
promise set up its own way of doing this - e.g. the DEL event cb may just
ecore_thread_cancel() for example (since ecore_thread takes care of this), then
i think this works and is simple.

> This lead to having an ownership problem, with parenting and reference
> counting issue. If everytime you call future_get you get a new Eo
> object connected to the promise, but not the actual promise itself,
> this solve all problem too. This solve the refcounting and parenting
> issue as the one who get the future is actually the one who own the
> future. This will increase the pressure on eo_add, but whatever.

or as above, just a single object, with the "thread" doing the work simply
listening for deletion. the cancel method also cancels the thread. if its not a
thread, then it's far easier as its just async i/o with the mainloop. in fact
that means a.lso having a cancel event on a promise sounds good because let's
imagine the following:

* call some method x() that returns a promise.
* inside x():
  1. create promise object
  2. create ecore_thread
  3. somehow store thread handle in promise
     (subclass and store in subclass data) or
     (eo_key_data_set(promise, "__mypromisedata", thread);) or
     (provide promise writer/owner api to store a void * in promise)
  4. set up DEL event cb
     (inside event cb - ecore_thread_cancel())
  5. set up CANCEL event cb
     (inside event cb - ecore_thread_cancel())
  6. return promise

of course the ecore_thread result cb will activate the promise "then" cb (or
else cb). the thread cancel cb in the mainloop just has to free any data
related to the thread action (same in the result cb after calling then/else).

#4 and #5 can actually just set up the same callback to handle both events, so
you don't have to write 2 event cb funcs. imho #3 should just have some promise
method to store a void * on the promise that can be used to store an
ecore_thread handle for example or some other object, struct etc. #1 and #2 are
unavoidable, as is #6.

and of course if there is no thred, but its async i/o like layers on top of eio
or ecore_con or ecore fd handlers and non-blocking read/write, then the above
is also just as simple as instead of ecore_thread_cancel() you just del the
ecore con obj or the ecore fd handler and all the data associated with it. no
race conditions to worry about.

> The promise/writer side will be an eolian object and can be inherited
> from. The future/reader side is I think to tricky and risky at this
> stage to allow it to be inherited from. As we clearly split both side,
> I think the future/reader side should be an Eo object only. In the
> future, if we are confident enough and find use case for exposing it
> as an eolian object and make it inheritable, we will still be able to
> do it, but for the time being, it is much more safe to not provide
> that feature.

if you are manually binding the object anyway then it's up to the bindings to
make this possible. in c++ if you make it a class, it CAN be inherited if you
like it or not. in js you can effectively inherit and extend, if you like it
or not. will this just "not work right" if you do it as it doesnt properly glue
back into eo?

but either way as above, i can see why you might want 2 objects. i can see how
this may make it simpler, but it means you assume threads are working with the
promise "owner" eo object. if it's done like above, then it's easy to do, easy
to manage, easy to handle writers work with the promise (they have to track
deletion/cancellation which is necessary anyway since we have a cancel func).

> -- 
> Cedric BAIL
> 
> ------------------------------------------------------------------------------
> Attend Shape: An AT&T Tech Expo July 15-16. Meet us at AT&T Park in San
> Francisco, CA to explore cutting-edge tech and listen to tech luminaries
> present their vision of the future. This family event has something for
> everyone, including kids. Get more information and register today.
> http://sdm.link/attshape
> _______________________________________________
> enlightenment-devel mailing list
> enlightenment-devel@lists.sourceforge.net
> https://lists.sourceforge.net/lists/listinfo/enlightenment-devel
> 


-- 
------------- Codito, ergo sum - "I code, therefore I am" --------------
The Rasterman (Carsten Haitzler)    ras...@rasterman.com


------------------------------------------------------------------------------
Attend Shape: An AT&T Tech Expo July 15-16. Meet us at AT&T Park in San
Francisco, CA to explore cutting-edge tech and listen to tech luminaries
present their vision of the future. This family event has something for
everyone, including kids. Get more information and register today.
http://sdm.link/attshape
_______________________________________________
enlightenment-devel mailing list
enlightenment-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/enlightenment-devel

Reply via email to