On Wed, 15 Jun 2016 13:41:06 -0700 Cedric BAIL <[email protected]> said:
> Hello, > > Ok, I am giving up on this. We will make it an eo object, but not an > eolian one as it should be a native type for any binding (It is sure > that C++, Lua and JS will have to do a manual binding for it) as there > is very little case were inheritance make sense on promise and > wouldn't at the same time break binding. eina_promise_owner will > become eo_promise and eina_promise will become eo_future (to follow > C++ naming convention). Not to sure how to limit the interface exposed > by a return type as we don't want the user of the API to access the > promise API, just the future one. Double object would be annoying, but > is likely the only solution. So if we want to be safe, we will need to > use 2 objects per promise. One facing the user of the API and one used > by the producer of the API. If we don't want to be safe, we can merge > both API and just use inheritance. So returning an eo_future interface > in the API, while in fact eo_promise function would work on it. what api should not be used? a lot of not most will need to be bound and exposed so you can CREATE a promise - e.g. if you create a new class in js and want to return promises or set them up etc. etc. and why not eolian. eo base uses eolian. you can make methods @protected for example... and why not inheritance? adding progress events to me at least is taking the basic promise without them and extending by adding. it's even then typesafe in c++ - you cant listen for progress on a promise that does not provide it. we don't do it right now but for events we could also type check in c too to see what events that class supports and runtime error/reject. if you now need not just progress but some other event along the way to completion, just inherit class and extend. > On Mon, Jun 13, 2016 at 7:23 PM, Jean-Philippe André <[email protected]> > wrote: > > On 14 June 2016 at 02:28, Felipe Magno de Almeida < > > [email protected]> wrote: > >> Sorry for top-posting. But let me summarize the Promise lifetime: > >> > >> A Promise when created starts with a ref-count of 1. > >> If the promise is not needed anymore, it should be > >> unref'ed (if no eina_promise_then is made, either > >> directly or by eina_promise_all/eina_promise_race). > >> > >> The first eina_promise_then _steals_ the first > >> reference, the others eina_promise_then > >> increments the reference count. > >> > >> When the promise is fulfilled (by value_set or error_set), > >> then each call to a eina_promise_then decrements > >> the reference count by 1. > >> > >> When the reference count reaches 0 _and_ the > >> promise is fulfilled the promise is deleted (both > >> conditions must be true, if just one is true it > >> continues to exist). > >> > >> So, valid cases: > >> > >> Eina_Promise* p = ..; > >> eina_promise_then(p, ...); > >> // promise will be deleted > >> // when callback for the then is called > >> > >> Eina_Promise* p = ...; > >> eina_promise_unref(p); > >> // Promise will be freed when promise is fulfilled > >> // by error_set or value_set > >> > >> Eina_Promise* p = ...; > >> eina_promise_then(p, ...); > >> eina_promise_then(p, ...); > >> // promise will be deleted > >> // when callback for the then is called > >> > >> Eina_Promise* p = ...; > >> eina_promise_all(p, ...); > >> eina_promise_then(p, ...); > >> // promise will be deleted > >> // when callback for the then is called > >> > >> Eina_Promise* p = ...; > >> eina_promise_all(p, ...); > >> // promise will be deleted > >> // when callback for the then is called > > > > So my understanding here is that this can work because a promise can not > > ever be synchronous. > > In other words, eina_promise_then can never trigger the success/error > > callback to be called synchronously, otherwise the above reference count > > system falls apart. > > > > While this approach is convenient, it means that we can use an object > > (promise) we don't hold any reference on (after first _then). > > This is weird :) > > Agreed. > > >> Etc.. > >> > >> On Mon, Jun 13, 2016 at 2:17 PM, Cedric BAIL <[email protected]> wrote: > >> > Hello, > >> > > >> > On Sun, Jun 12, 2016 at 10:13 PM, Jean-Philippe André <[email protected]> > >> wrote: > >> >> On 13 June 2016 at 03:02, Cedric BAIL <[email protected]> wrote: > >> >>> On Wed, Jun 8, 2016 at 4:16 AM, Carsten Haitzler <[email protected] > >> > > >> >>> wrote: > >> >>> > On Mon, 6 Jun 2016 06:01:13 +0200 Cedric BAIL <[email protected]> > >> >>> said: > > <snip> > > >>> Events are the same: they call a callback function with a user data and > >> an > >> >> event info (promise value). > >> > > >> > No. Event in promise will keep their value until all the reference to > >> > the promise exist and each time that a callback is triggered that > >> > reference count goes down by one. There is also an absolute guaranty > >> > that you can not destroy a promise without having all the reference > >> > receiving either a succeed or a fail. Also the returned value of an > >> > event handler for then or cancel should be ignored as you can not stop > >> > notifying anyone in the chain and the state should stay either success > >> > or failure once it has been decided. > >> > > > > It is actually a good question whether the return bool is a good idea or > > not. > > If you return false in evas callbacks, you're gonna be in trouble. > > > > The ON_HOLD flag, now called efl_event_processed_get/set() is a better > > approach to stop processing events. > > That is off topic, but seriously something we should consider asap if > we want to drop the return type of event. I have not any case in mind > where returning EINA_FALSE make sense. Should we drop it ? > > <snip> > > >> >> Anyway it seems the only difference here is that a promise starts the > >> >> action as soon as possible, while an eo object would have to > >> explicitely be > >> >> marked as ready (which is very similar to starting the action during > >> >> eina_promise_then). > >> > > >> > No, the main difference is that the life cycle is linked to the > >> > callbacks and that their should not be any way to bypass it. eo_del > >> > should also be forbidden for example on a promise as only a cancel > >> > make sense. Of course we could alias it, and make sure that cancel > >> > don't destroy the parent. We can also override all eo event API and > >> > make sure they do what we want, but we can't at the moment override > >> > eo_ref and eo_unref. The alternative would be to create an Eo_Promise > >> > which doesn't inherit from Eo_Base (Or make an Eo_Light that both > >> > would inherit from) and would kind of make clear that it is not an Eo > >> > object, but a promise object (Given that eo_ref and eo_unref become > >> > virtual function). > >> > > >> > Also at which point do you think user are going to be confused by an > >> > Eo object where every single function call on it has its own > >> > documentation and doesn't behave like a normal eo object ? > > > > That's where we still disagree :) > > > > I still have trouble understanding how fundamentally different those two > > objects are. > > In fact I see a lot of similarities between a (conceptual) promise and > > Efl.Part. > > > > From my understanding, the main difference is that a promise callback WILL > > be called, be it the error or success, one of them will be, for each _then, > > _race and _all that was setup. Which can be enforced with a commit approach: > > > > // same syntax as eina_promise: > > p = promise_function(obj) > > eo_promise_then(p, _success, _error, data) // this is a HELPER based on eo > > events, implemented in Eo.Promise, steals the ref > > > > > > // it would be equivalent to: > > p = promise_function(obj) > > eo_event_callback_add(p, PROMISE_EVENT_FAILURE, _error, data) > > eo_event_callback_add(p, PROMISE_EVENT_SUCCESS, _success, data) > > eo_promise_commit(p) // steals the ref > > > > > > // or: > > p = promise_function(obj) > > eo_event_callback_add(p, PROGRESS_EVENT, _progress, data) > > eo_event_callback_add(p, PROMISE_EVENT_SUCCESS, _success, data) > > eo_event_callback_add(p, PROMISE_EVENT_SUCCESS, _success_watcher, data) > > eo_event_callback_add(p, PROMISE_CANCEL_SUCCESS, _canceled, data) > > eo_wref_add(p, &p2) > > eo_data_key_set(p, "my data", stuff_that_i_need) > > eo_promise_commit(p) > > > > etc... > > commit doesn't work well with bindings and library that will not know > when to commit a promise that is given to them. Basically only case > where commit is to be called is in the application itself and never in > any API that expose one. I don't think this is a solution. > > Only viable solution if to be done with eo is if eo_ref and eo_unref > either send a message or can be overriden. If so, we can implement the > following : > > p = promise_function(obj); > eo_promise_then(p, &_then, &_cancel, &_progress, NULL); > > and > > p = promise_function(obj); > eo_ref(p); > eo_promise_then(p, &_then, &_cancel, &progress, NULL); > all = eo_promise_all(p, p1, p2, p3); > race = eo_promise_race(p, p2, p2, p3); > eo_unref(p); > > We would silently eo_ref in eo_promise_then and eo_unref would start > acting if the number of ref == number of function. Once it start > calling each function, it would eo_unref and the last call would drop > all reference to eo, destroying the object. > > > _race and _all could be implemented in Eo.Promise, and would make the _all > > promise get an extra ref on the sub promise. > > As _race and _all are most likely already existing as a native object > in all bindings, it will be only useful for C. Implementing them on > top of an Eo.Promise wouldn't be a real problem and we can make them > more convenient as we do not need to follow eolian constraint there. > > > And then the eo event callback data is "data", the event->info is the value > > (void* anyway). > > Yes. > > > Internally, all we need to make sure is that all the callbacks will be > > called (error or success), and the promise object can't be deleted until > > then. > > We need to also override eo_del to actually act like a promise_cancel. > > > Also need to ensure that we unref() the promise object after it called its > > callback (this can be done in each promise implementation - no infra). > > > > What happens if cancel() is called during a success callback? Will the > > cancel or error cbs be called? Anyway this is a tricky situation, similar > > to eo_del() during a callback. > > This is forbidden. The state of a promise is defined once and for all > by the first value set or cancel. eo_del will have a warning and do > nothing on a promise which as already succeeded, but hasn't finished > yet for whatever reason. If it doesn't follow that rule, it breaks > assumption on promise making them pretty much useless. > > > Now, if you forget about Eo, Eina, ... and go back to C++, you will agree > > that anything is an object. A promise would also be an object, an instance > > of a class. Why would it be any different with our object model? > > Promise would be a template provided as a native type in C++ and be > named future. C++ object model let you implement a lot of different > life cycle management, funny GC for example, without enforcing > anything. There is no such thing as eo_ref/eo_unref on a C++ object. > This is something you implement yourself on top of C++ object model. > Same goes with weak ref or smart pointer. They are something you > implement on top of the language. This is not the case of what eo > does. Eo come with its own life cycle management, and we currently > can't implement promise without change to eo and overridding a few > base function (ref/unref and del for sure, not sure for weak ref and > friends). > > Every language now provide this as a native type. > > > So, yeah, still not convinced we need a different event signature, a > > different ref/unref system (where, as seen above, we can manipulate objects > > of which we don't own any ref), and lose on the way all the fancy features > > that eo provides. > > With change to eo, it is doable. Still think we are forcing a cube > into a smaller cilinder, but well, I have some good hammer, so > whatever ! > -- > 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. http://pubads.g.doubleclick.net/gampad/clk?id=1444514421&iu=/41014381 > _______________________________________________ > enlightenment-devel mailing list > [email protected] > https://lists.sourceforge.net/lists/listinfo/enlightenment-devel -- ------------- Codito, ergo sum - "I code, therefore I am" -------------- The Rasterman (Carsten Haitzler) [email protected] ------------------------------------------------------------------------------ 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. http://pubads.g.doubleclick.net/gampad/clk?id=1444514421&iu=/41014381 _______________________________________________ enlightenment-devel mailing list [email protected] https://lists.sourceforge.net/lists/listinfo/enlightenment-devel
