On Wed, 15 Jun 2016 13:41:06 -0700 Cedric BAIL <cedric.b...@free.fr> 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é <j...@videolan.org>
> wrote:
> > On 14 June 2016 at 02:28, Felipe Magno de Almeida <
> > felipe.m.alme...@gmail.com> 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 <cedric.b...@free.fr> wrote:
> >> > Hello,
> >> >
> >> > On Sun, Jun 12, 2016 at 10:13 PM, Jean-Philippe André <j...@videolan.org>
> >> wrote:
> >> >> On 13 June 2016 at 03:02, Cedric BAIL <cedric.b...@free.fr> wrote:
> >> >>> 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>
> 
> >>> 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
> 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


------------------------------------------------------------------------------
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
enlightenment-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/enlightenment-devel

Reply via email to