On Wed, Jun 8, 2016 at 4:16 AM, Carsten Haitzler <ras...@rasterman.com> wrote: > On Mon, 6 Jun 2016 06:01:13 +0200 Cedric BAIL <cedric.b...@free.fr> said:
<snip> >> >> You just can't do with eo event what promise do. Eo event are a >> > >> > it's not NECESSARY to do anything new. timeout can be an eo obj that >> > deletes >> > itself after the one-shot callback. it doesn't need a promise. same as job. >> > i can't add promises as children to an obj and make sure they get >> > autodeleted when parent is. i have to do this all by hand now. >> >> It is a terrible mistake to override eo object lifecycle. This is an >> absolute no go as a solution. Anything that bypass the refcounting and >> ownership of an eo object lead to massive issue and trouble. We can >> not implement auto deletion of eo object outside of the reference >> count system. > > this doesn't bypass it. it USES it. the object unrefs/del's itself. when done. > when an evas canvas is deleted it deletes all child objects. no code is > explicitly in the app deleting the objects. it's done internally. That's exactly what I mean by bypass. Evas canvas delete object because the parent die. Now, in the case of a promise eo object, there is no parent that will disapear to do the unref/del, it is when all the listener have received the value, that the promise disapear. If you want to use normal eo lifecycle for that, it means that the object has to delete itself. And this is bad. This is exactly what ecore_timer where historically doing. They were not linked to any parent and would just vanish under your feet. This is what tricked you into thinking the bug was in the timeout promise while it was in the handling of the lifecycle of the timer itself. Reading what you say, you are advocating for using the normal eo lifecycle and not letting itself commit succide, which is the proper way to handle eo object. Now how can that work with promise ? No idea. >> > efl model needs to drop promises. ask sanghyeon and sub - they are hating >> > to >> > work with the promises in efl model - it's massive overkill and unneeded. >> >> If you read the ongoing discussion regarding MVC and the view list >> code, you will see that the problem is not the promise, but the fact >> that the model is fully asynchronous and that they have to handle it. >> Dropping promise out of the model, and they will not only hate, they >> will want to jump by the window. > > it's both. async made it more complex than sync AND promises require a unique > promise per property on a model object when a simple "property loaded" event > on > the model object would do just fine. the one cb can refresh the item mapped to > the model object in whole and a property get can just return null etc. if the > property is not loaded yet. property content has to in the end be cached in > the > model object anyway so this ends up simpler and you don't need a promise nor > the value - the value is already living in the object under the property. Returning NULL change absolutely nothing to there problem. It just means they have to keep fetching and fetching until they have all the property resolved. Even worse, they have now no synchronisation primitive to do that for them at all. You know with promise they have promise_all to know when everything is finally settle down, because there problem was how to find the final size of an item if you don't have all it's data. So you need to keep fetching all the property you need to display it until they are all there. Then you can stop, learn the size and move on. Your solution doesn't simplify that at all and you have no synchronisation helper anymore ! It add complexity as this is what we had before. As I said, that's what we had before, and it was way more complex. Now in the case where we do force all data to be available before we notify them, so that they avoid there problem (which was to wait until everything is there), it obviously create delay problem as the time needed to finish fetching all property can be quite long. Expecting only to have all data available in one request make absolutely no sense. Let's take two examples : - An avahi model will be able to give you an ip right away, but it won't be able to give you the name right away. That part is asynchronous. So what do you do ? Wait for the network to be done fully filling that entry before you can actually access any of it ? This is likely going to be the case with a lot of network model, multiple request to build the model delaying the availability of the data to until all of it are fetched. - Io model. If you are listing the content of a directory, you get to know right away if it is a file or a directory and you also get the filename directly. You need another system call to get size and access right which will take longer. Also at some point we should integrate with efreet to allow easy linking of the type of the file to an icon name that could be connected to efl.ui.icon. Obviously the time between when you actually know the first group of information and when you get the information of the last group will be huge. You can also proxy model into other model. Now, this increase the complexity in the proxy model as it has to wait for the proxied model to be done fetching everything before annoncing anything. All the synchronisation problem are to be handled manually there. So you will agree with me, that you need support for fetching individual property individually. Be it with promise or by returning NULL, you need indepedent fetching of each property and a notification when each of them get done. Now, I think you are better of with synchronisation primitive like promise_all than by doing everything manually. The only thing I think we may need at some point is a grouped promise fetch so that you get a batch of data at once and the model does handle the synchronisation needed to provide all of them into one operation. This would reduce the amount of callback needed and quite likely improve performance. That is an optimisation that is completely doable in the current design of promise and can wait for later. <snip> >> >> repeated event which doesn't allow any easy synchronisation and lead >> > >> > wrong. you can in the callback just do the next action and delete yourself. >> > it is possible to do this easily enough. but this isn't the common case. >> >> Yeah, this is going to make life easier by writing more code that is >> likely to be the source of more problem. > > and eina_promise isn't more code? it's new/different to the rest of events and > objects? eina_promise objects have no safety and ate causing crashes now where > none were before and will continue to cause more and more and more. it will > cause much more time spent debugging and complaining that efl is "horrible" > and > "hard". As said before, moving our internal code to use eina_promise has reduced our size of code for mvc by 30%. As for the safety, I already agreed about using the same kind of infra as Eo_Id and that's absolutely no big deal. There is nothing to win with Eo and Event. <snip> >> to implement the asynchronous behavior. Writing a new data model for >> MVC has also been a huge pain until we switched to promise. So yes, I >> have been experiencing first hand what writing asynchronous code is. >> Same goes for Felipe. I am not going to switch away of a solution that >> make our life seriously easier. I will improve the solution, but not >> walk away from its design. It is way way way easier to implement >> safely asynchronous behavior with promise than with your proposition. >> This has been tried and the outcome has been clear for anyone involved >> with that previous experiment. > > eina_promise is not ready. it's unsafe. it's more complex. it's a new kind of > object that doesn't behave like any other object and lacks the safety and > convenience. if you say objects' can't delete themselves then what on earth > are > promises? are they not objects? are they not something you hold a handle to so > you can cancel them or otherwise interact with them? do they not have a > lifecycle? are they not created and destroyed like eo objects? ye somehow > promises can delete themselves (e.g. the eo timer object a timeout created was > deleted then the promise is deleted silently on its own in the background...) Promise are a promise to deliver something in the future. In themself they have no propery and no function. They aren't object, they are delivering object. Their lifecycle is that they either deliver or fail, they never "die" before that. It is a guaranty that they deliver a callback whatever happen to everyone that registered to listen them. This doesn't match at all eo object lifecycle. > you are totally inconsistent thinking promises are some kind of magically > special thing that is not an object... yet in all ways it works *IS* an > object. If you stretch the definition of an object outside of what Eo is, yes, but by that standard everything could be an object. If you limit your definition to what Eo is and I mean by that Eo lifecycle and events, it doesn't. Oh, and there is plenty of stuff in an Eo object that are useless for promise. >> > promises are not eo objects. they cannot be managed in the lifecycle of >> > object. jobs and timeouts now need special handling. the promises for >> > models are not eo objects so you have to specially handle them if you want >> > to cancel and there actually just is little point in doing so actually. >> > >> > you can't make promises weak refs. you can't add them and children to a >> > parent for auto-deletion. they can't be easily extended (adding more events >> > to a promise) like eo objects can. >> >> You never want weak refs, you don't want either parent/child > > why do i not want them? tell me? why do they even exist then as an idea and > why > are they in eo? if i want a weak ref then that's what i want. i want a handle > that the object system will set to NULL for me when the obj is deleted so i > don't have to do that by hand by adding a del callback and nulling the ref > myself. so... why don't i want them? i can tell you that e, efl etc. is full > of > this kind of "track del event and NULL a ptr" code. it's all over the place. > so... why? Because you are only interested in the result of the promise, not in the promise themself. You don't track the life of a promise, because you do that the moment you register the then/cancel callback on it. If you do not need the result of the promise, you cancel it and that is the same as if an error did happen. As said before, we may need a way to automatically cancel a promise once an object is deleted, but you do not need to keep a promise around because an object is still alive. That's because the object is not using the promise, it is expecting its result. Something along eo_promise_link(obj, promise) is the only thing we need. <snip> >> when handling asynchronous stuff). And implementing that behavior in >> Eo is going to be a pain (disabling refcounting, disabling >> parent/child, ...). > > eh? don't disable refcounting. in fact WTF is this?... > > EAPI void eina_promise_ref(Eina_Promise* promise); > EAPI void eina_promise_unref(Eina_Promise* promise); > > you speak of not refcounting yet eina promise has RE-IMPLEMENTED reference > counting just like eo. i can't take what you say here seriously. if you say > promises are not objects and should have no reference counting because they > are > oh so special yet... right there in eina_promise is EXACTLY THAT. eina > promises > are re-inventing eo objects thinking they are oh-so-special > not-object-objects. This is the refcounting of how many callback then/cancel are to be registered and a protection against deletion when running them. This is not like eo_ref/unref as they do not refcount the same kind of thing (number of user vs number of callback waiting for a result). >> >> Also last point, I think having the same signature, would actually be >> >> more confusing to people. Like why does that event not accept to be in >> >> a promise_all or promise_race ? If it has the same signature, people >> >> would expect to be able to use random event in promise_all/race and >> >> that is just not doable. >> > >> > the number of times people actually NEED these is insanely rare. no one is >> > using them. these "features" cause more pain than it's worth. speak to the >> > people using promises now. >> >> Ofcourse they don't need it, they never write any asynchronous code. >> Almost none of our API is asynchronous and when they can they run away > > no. i am speaking of the cases where promises have crept in. timeouts are not > needed when timers will do. jobs could just be objects like timers that > self-del after calling their "done" callbacks. eina_model could work without > promises just fine (see above). any kind of event with "do something now and > later some event happens as a result" is async. we've had this in efl for ages > in several corners. edje objects are async by design. signals are queued and > will pop out later in their callbacks. i shouldn't have to tell you this. edje > - one of our biggest cornerstones of everything we do is async. preload - > async. jobs - async. timers - async... ? Yes, they are async and yet there is no generic solution to synchronize any of them. Result our API is harder to use as you need a lot more code to synchronisation and make sure you didn't miss anything. Promise do guaranty you that when you did register your callback, you will get called, one way or another, whatever happen. It is just two cases to handle, come with a few handy synchronisation primitive and are simplifying a hard problem. Yes, asynchronous API are hard for people. Having no primitive at all to handle it, doesn't make our API simpler to use, it make our API harder to use. Eo is not the answer to all problem. It has draw back in some case, like this one to use it (Namely performance cost, memory cost, unmatching lifecycle and unmatching event). <snip> >> > why should a timer be so DIFFERENT to a timeout? why should it be a special >> > thing with a whole different way of working with promises? why add the >> > complexity? just set a timer to NOT REPEAT on creation... having all the >> > code for a timeout is needless complexity in our codebase AND in the api as >> > people have to figure out a completely different way soemthing works. >> >> So your point is to have the timer just stop emiting event and you >> have to kill it manually afterward. Doesn't look any easier to me. You > > no. it just deletes itself. promises do just this already! > >> have more code to write and more chance to go wrong. The fact that > > no you don't have more code. well "more" would be to set he timer to not > repeat > on creation. > > timeout = eo_add(parent, EFL_TIMER_CLASS, > efl_timer_repeat_set(eo_self, EINA_FALSE), // this extra line > eo_callback_add(eo_self, EFL_ACTION_DONE, callback, NULL); > > with timers being eo objects and timeouts being promises i have 2 vastly > different pieces of code than i have to learn about 2 different kinds of > objects that work differently and use different api's. Because they are different in nature. The first one is an object the second is the guaranty to either deliver something at a specific point in the future or fail. >> they don't do the same thing, means they are not the same. We could >> sure merge everything together by this standard. Not going to make >> anything easier. Having explicitly different object for different >> behavior make things easier, not the opposite. Otherwise we should >> merge back all this image object, because they all display pixels in >> some way or another. > > it make's it harder to learn, more api's to learn, difference to figure out, > which do i use where etc. etc.- you add a learning curve that is simply not > needed. don't want ti to repeat? turn repeat off once above on creation. Having more focused and dedicated API make life easier as each object are less complex. Otherwise we go back to the old Evas.Image which should be easy to use as it could do everything. The problem is not on the number of object and API, but on how clearly separated they are and how much they deliver something different. <snip> >> the problem that I got described are: "It is to asynchronous, we want >> result directly.". That is not going to happen and with your >> proposition it will be just worst. Been there done that, not going >> back there any time soon. > > how will it be worse? the model object stores its properties? a gegt is an > immediate get from the stored property data? you use events just to indicate > new property data arrived? (event info can indicate which property it is that > arrived if they care)? how is that worse? Well, how do you now know when you are done ? You have to do all tracking by yourself, with promise, you have promise all. You also have to do a manual check for each data fetch to see if it is NULL or not. You increase the chance that someone will complain why is my data NULL and people have to fetch all property every time there is an update to just count things. I don't see at all why you think it is simpler and less code. Experience as told us it wasn't. <snip> >> > see above for model. same for job and timeout. they don't need them. i >> > haven't looked at eldbus or eio but i think its pretty much the same deal. >> > you don't need them. >> >> It's pretty easy, just git log -u on the any of the model and the >> elementary view to see how much more work it was before the promise >> (Keep in mind that it was also buggy and more difficult to >> develop/fix). You proposition has been tried in the past and it has >> been a complete failure. > > it has not. let's go to a long standing one - preload. that has been around a > long time and how has it been a failure? explain it to me. we won't talk model > as it barely has even existed or been used long enough to say. How many people use it instead of just doing a show ? How many user of genlist complain about it being slow while they don't use preload on the image ? I know that they are having anyway some filesystem access with the header, but doing a full image decompression is worse. I am pretty sure most people don't, because we have had a bug in preload until 1.18. If you heavily use preload, you would end up with a crash (like the one edje_cc was suffering from). So yes, you use it, but I bet that most people don't and I am pretty sure that any use of preload in genlist would have triggered the bug in previous efl release. >> > this is the same as eina_promise. i have to do eina_promise_then() AFTER i >> > get the eina promise back - eg from job or timer. but what you do is you >> > dont need a promise at all above you just do: >> > >> > eo_callback_add(image, EFL_IMAGE_EVENT_LOAD_SUCCESS, cb, NULL); >> > eo_callback_add(image, EFL_IMAGE_EVENT_LOAD_FAIL, cb, NULL); >> > efl_file_set(image, "tot.jpg", NULL); >> > >> > i set up to listen before i do the action. simple. it works WITHOUT a >> > promise. >> >> Thanks for an example that doesn't work. Either you add a call before >> registering all the callback to force synchronise the previous >> possibly running file set or you have to handle in both callback the > > err how does it fail? you dont dd cb's every time you file_set. are you mad? > the code that is controlling the file set sets up the cb's once and listens > for > when things succeed or fail, then does something appropriate. how does this > fail? So what happen if there was already a file being set asynchronously on the object ? >> case where the event you receive is not for the file you are just >> opening after. So your example is misleading on the complexity on > > how is it misleading? you set up cbs once. you file_set. any new file_Sst > cancels a previous one so no cb will be called for any previous ones. any cb's > called after that are for the last file_set. how does it fail? That is a synchronisation bug to happen. How other pieces of software will be notified that the previous file set request has been cancelled if they are not getting the callback at all. You either add a new callback that they have to listen to or you trigger the cancel callback. In which case you have trouble. >> purpose. Oh and with promise their would be no misleading behavior as >> the previous promise will have automatically been cancelled and the > > it isn't automatic. the file_set explicitly tracks the previous promise and > has > to cancel it. it's the exact same thing. Yes, except that the previous promise will deliver a cancel to everyone and it will be explicitely related to the request they registered for. No need to filter things out ala Ecore_Con events or to have addoc synchronisation in the application. >> new one will have been completely independant. Thanks for giving me a >> good bad example with your proposal and why people have not implement >> much asynchronous behavior with our current API. > > wtf? it's no more code at all. it's 2cb's added as event cb's and a file_set. > i > don't have an ADDED promise object to deal with at all. it's simpler. not more > complex. We both know that dealing with event filtering is a very bad pattern, and very explicit reason why people don't like Ecore_Con API. So what is your work around ? You keep focusing on the code that just set callbacks as if it was the end of what you are writting, but forget about the added complexity in the callback themself. <snip> >> >> is no way to get any event. Ofcourse, we can override the behavior of >> >> events on this eo_promise completely. Now let's imagine, that we >> >> actually do always store the events, so that everytime someone >> >> register a callback we can send the event. Still you can't auto del >> >> the object at any point in time, you have to force the user to >> >> implement the eo_del and to always provide both a then and cancel >> >> callback. >> > >> > you have the same issue with eina_promise if you return it. EXACTLY THE >> > SAME. it has no cb's for then/fail yet. >> >> No, promise keep in memory the result until you register all the >> callback you have planned to register. There is no race condition at >> all. That is why you pass a free method when you set the value. It is >> to clean it later on and to keep it around until you are done. So no, >> it is NOT THE SAME. > > and if you pass in an eo promise object it can be done similarly - just set up > cb's on the promise obj before passing to the action. the model stuff works > this way - promises are passed in not returned. Rellying on the order of callback being registered is a recipe for complain. I can see people complaining why they don't get their callback already. Also you would need to do the full setup of your promise including all the promise_race and promise_all before you set up your request. This is a huge requirement and restriction. > and you can do the same with eo - you can store the result until cb's added or > until a go/done/whatever api is called. but that on;y matters if you want a > specific cb for that specific action. in general if you want that hen you want > a real object to be returned so you can manage it like other objects. As said before, basically what you want is an Eo object which doesn't behave like a normal eo object. Having its own meaning for ref/unref, for events and life cycle. At this point, I don't see how it will be easier for people and not more confusing ? >> If history tell us, our existing solution is not usable, but prove me >> wrong and show me how amazing our current limited set of asynchronous >> API is used by so many people. Now just think that we are expanding > > as above. ecore_con. ecore_con_url, preload, timer, job, animator, .... all > used. We both know that people complain about our ecore_con api a lot and that preload was not used much until now. > what we learned is these are objects that need tracking and that is a pain and > that is why we have eo. you are now choosing to abandon that lesson with > eina_promise. I am not. We have also learned that they are a pain to deal with because of a lot of other reason than just it not being eo, on of them being also synchronise things together is a pain. You know tracking things and making sure that you stop caring about your timer timeout when you have connected and stuff like that, but sure it is just registering a few callbacks and using refcounting. >> the amount of async API and image the result. I see it already, as >> many data model as we have user of elm_store, as many view as we have >> user of image async preload, ... I can see that success already. > > we have very little async api. almost all of them are used. > > we're repeating here. > > eina_promises are objects. they just refuse to be eo objects and so be totally > different in usage. this is bad. it means no safety. it means different > callback signatures etc. - as above. this is worse than what we had with eo > until promises turned up. far worse. and it's worse than legacy api because > you > lose the benefits of eo AND make the code longer. As said before, what you are advocating for was what model was before promise. It was exactly that and it was 30% more code all over the place. So please check our history of code and see that your assesment of it being more code is wrong. As for the benefit of Eo, it is now in, we are using the same kind of infra as Eo_Id for promise. >> No, you didn't, I did. You completely missed the problem. The issue as >> to do with timer that have a problematic lifecycle. Historically timer >> where automatically destroyed by the main loop when the main loop was >> destroyed. This behavior is still there and by pass the ownership >> behavior of eo reference (like your proposal for having an >> automatically deleted eo object). So I needed to watch for the timer >> to vanish under the feet of the timeout. This was badly done on my >> side as I was just watching the DEL event on the timer. Obviously any >> eo_del o the timer does lead to that event, which created the double >> free. Promise could be more resistant and prevent double cancel and >> double value set (which they will soon), but the main fix is to fix >> the timer lifecycle properly and watch the main loop deletion, not the >> timer destruction. So your analysis of why promise is bad is based on >> a lifecycle issue on an eo object which is doing exactly what you >> recommand to do. Seems like you should revise your proposal as it did >> obviously misslead you into not fixing a bug properly. > > umm i sat here and looked at the backtraces. i sat in valgrind. you cancel > promise. it dels' timer obj. del cb on timer then wants to cancel promise > again. then it falls over in a big stinking heap. i shortcut it so on cacnel > this loop wouldn't happen. it worked. it didn't leak. but it points out how > fragile promises are. It did leak, just not in the case you were testing, but whatever it was a bug in promise as it was obviously in the backtrace and eo can not be the source of the problem even when it pops up in the backtrace. -- Cedric BAIL ------------------------------------------------------------------------------ What NetFlow Analyzer can do for you? Monitors network bandwidth and traffic patterns at an interface-level. Reveals which users, apps, and protocols are consuming the most bandwidth. Provides multi-vendor support for NetFlow, J-Flow, sFlow and other flows. Make informed decisions using capacity planning reports. https://ad.doubleclick.net/ddm/clk/305295220;132659582;e _______________________________________________ enlightenment-devel mailing list enlightenment-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/enlightenment-devel