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