On 19/06/16 02:52, Carsten Haitzler wrote:
> On Fri, 17 Jun 2016 09:57:47 +0100 Tom Hacohen <t...@osg.samsung.com> said:
>
>> On 17/06/16 03:53, Carsten Haitzler wrote:
>>> On Thu, 16 Jun 2016 20:11:09 +0100 Tom Hacohen <t...@osg.samsung.com> said:
>>>
>>>> Lets start with life-cycle: Eo is great, and I think using Eo is the
>>>> right way to go, but unfortunately that doesn't solve our life-cycle
>>>> issue. When do promises die?
>>>>
>>>> p = efl_file_set()...
>>>> // Delete here if file has been set?
>>>> promise_then_add(p, cb)
>>>> // Delete here if file has been set?
>>>> promise_then_add(p, cb2);
>>>> // Delete here if file has been set?
>>>> ... // a million years into the future
>>>> // Delete here if file has been set?
>>>
>>> the way i see it is you need to set both then and else at the same time so
>>>
>>>   p = efl_file_set()
>>>   eo_promise_then(p, sucess_cb, fail_cb, NULL);
>>>   // p may be deleted at this point since on success or failure it is
>>> deleted // do not depend on p after you have set then/else cb's. ensure if
>>> you need to // access the cb that you add a DEL event cb to the promise to
>>> track it OR if // you HAVE to have it then add an eo_ref(p) before
>>> eo_promise_then()
>>
>> Unfortunately, I don't think that works well in real life. It'll be a
>> source of many bugs. The problem is that:
>> p = ...
>> eo_promise_then(...)
>> eo_promise_then(...)
>
> we have eoid to help here... but who would ad 2 then's. we should have the 
> 2n'd
> then be an error so it'll ERR() saying then is set twice. then the programmer
> gets that message every time their code runs and they know to not do it and
> sometimes if the promise is deleted eoid will ten barf on the id, but you'll
> keep working.
>
> make the then only be ae to set cb's once at all. problem solved.

We talked about it on IRC, there are cases. In JS in particularly it's 
very common to do:
p.then().then().then()
I don't remember exact uses for that, but a more obvious usage is:
download1.then(tick_a_v)
download2.then(tick_a_v)
all(download1, download2, tick_the_main_v)
race(download1, timeout, timeout_err)
race(download1, timout, timeout_err)

It's very cheap to deal with if they are eo events.

>
>> Will work in many case, until it doesn't sometime when we change
>> something internally, or when the stars align just right and the promise
>> evaluates immediately. This is very dangerous. This is more common than
>> you think, and will become even more common. In JS, the usage often
>> looks like:
>> p.then(...).then(efl_provided_helper_cb).then(other_efl_cb).
>>
>>>
>>>> There is just no sensible way to do it automatically. You will *always*
>>>> have to unref, so following the above example:
>>>>
>>>> p = efl_file_set()
>>>> ... // All of the code before
>>>> eo_del(p); // It'll only die here
>>>>
>>>> Which won't work because then ignoring efl_file_set's output won't be
>>>> allowed.
>>>
>>> well that's kind of the problem. with no then/else the promise has to stay
>>> around forever holding the return value. you can't ignore it if its a
>>> return. if it's
>>>
>>>   p = eo_add(NULL, PROMISE);
>>>   // do aother promise setup here like
>>>   eo_promise_then(p, done_cb, NULL, NULL);
>>>   elf_file_set(obj, file, key, &promise);
>>>
>>> then it can set up the promise in efl_file_set. if you do
>>>
>>>   efl_file_set(obj, file, key, NULL);
>>>
>>> then we say "we don't care about the async result". perhaps it can now be
>>> sync by default if you do this?
>>
>> Look at my suggestion below, I already solved this problem.
>>
>>>
>>>> The only sensible way of doing it, I guess, is to force a wrapper of
>>>> some sort, so the code above becomes:
>>>> p = eo_ref(efl_file_set());
>>>> ... // Code from before
>>>> eo_del(p);
>>>>
>>>> Or probably for extra safety (like marking the promise was actually
>>>> used, and not just implicitly with a ref, this will allow us to block
>>>> then/cancel registration and be more safe).
>>>>
>>>> p = efl_promise_use(efl_file_set());
>>>> ... // Code from before
>>>> eo_del(p);
>>>>
>>>> efl_promise_use will set a flag in the promise so that
>>>> p = efl_file_set();
>>>> promise_then_add(p); // This will fail because the flag wasn't set.
>>>>
>>>> So that's safe and probably the way to go. This will let us manage
>>>> life-cycle correctly.
>>>
>>> i think that's more complex than the above i suggest. the problem is if you
>>> pass in a promise... this now affects all of our file_set or any api that
>>> can or should be async.
>>>
>>> as i said... i don't think we need a promise on these objects. we already
>>> have an object to store the value/state of the load. it can already call
>>> event cb's when these actions succeed or fail. we have done this with
>>> preload for years already. if you do another file_set it does cancel the
>>> previous one by definition (the only q is if that means you have to call a
>>> load fail callback of some sort).
>>>
>>> this is what i mean by "let's not use promises here because at this stage
>>> they do not help, just cause more work, complexity etc.".
>>
>> I 100% agree on this, we don't need to use promise for file_set! Using
>> file set was just an example though for the life-cycle issue. The
>> life-cycle is the problem I was addressing here, and I don't think it's
>> solved in any way but my last example.
>
> i dislike making people have to del their promises when they can be taken care
> of by themselves. look at timeouts and jobs. they are promises now and if you
> have to create a job that returns a promise... then have to del it
> but it will later be called... that just looks WRONG. reading such code makes
> it look broken. it'll be confusing to people to no end. having a single ref 
> and
> that ref is unreffed after then/else is called will be just fine. only allow a
> single then and/or else cb to be set up. :)

I suggested we do the same we do for proxies.
p = file_set()
p.then() // unrefs p

While:
p = eo_ref(file_set())
p.then()
p.then()
p.then()
eo_unref(p) is allowed and encouraged.


>
>>>
>>>> Usage of event callbacks: I mentioned it somewhere else in the thread,
>>>> but not as bluntly. I think Marcel is wrong, and I think you guys are
>>>> focusing too much on non-existent semantics. Saying promises are
>>>> callbacks that are only called once so they are inherently different
>>>> from event callbacks is absolutely wrong. Think of EO_EVENT_DEL, called
>>>
>>> i totally agree with you on this.
>>>
>>>> when object is deleted, only called once. You are too fixated with how
>>>> events happen to be implemented in eo.base, don't.
>>>
>>> i agree.
>>>
>>>> As I also said, overriding callback_add and adding there code to call
>>>> the callback immediately if the promise has already finished is
>>>> *exactly* the way to go. Also, you don't need to remove callbacks once
>>>> they have been executed, they just happen to never be called again
>>>> because the callback is never triggered again.
>>>
>>> agree - but i think the then/else would do well to be special for eo
>>> promises (for the reasons already given). progress should be an eo event
>>> etc.
>>
>> I'm OK with having helpers, though I don't think they are necessary.
>>
>>>
>>>> Splitting of promise to two objects, owner and future: unnecessary.
>>>> There are a few mechanisms in Eo to let you have different "access" to
>>>> an object.
>>>
>>> i agree. single object, but 2 interfaces. a future and an owner interface
>>> on a promise obj.
>>>
>>>> 1. Make all of the owner methods "protected", so assume whoever is
>>>> implementing "owner" is more responsible and let him have access to both
>>>> the "future" functions and his "own".
>>>
>>> this sounds good.
>>>
>>>> 2. Same assumption as #1, but just make Owner inherit from Future, and
>>>> create Owner internally, but return Future in the API. Won't have a
>>>> different in C, but for bindings it'll only expose the correct type.
>>>
>>> well futures and promises for at least several languages need to be manually
>>> bound. but a quick look shows lua does not have promises IN LUA. there are
>>> libraries that implement them (promises/futures) but it's not a language
>>> construct. c++ doesnt have it either. it's in sdtc++. i am unsure for
>>> js/node where they stand but given node.js has them they can be assuemed to
>>> be a core of the langauge in a node.js environment.
>>>
>>> but for lua we will want to have actual promise objects with out methods
>>> exposed in lua like everything else... so we DO want at least some auto
>>> generation for eo promise and perhaps just a special case for
>>> eo_promise_then() like eo_callback_add/del are special.
>>>
>>>> 3. If you don't want to restrict yourself to the assumption made in #1,
>>>> that the implementer of Owner can be trusted to know what he's doing,
>>>> you can create two classes and two interfaces.
>>>
>>> i actually prefer this by far.
>>>
>>>> abstract Efl.Promise
>>>> interface Efl.Promise.Owner, implements Efl.Promise, adds Owner API
>>>> interface Efl.Promise.Future, implements Efl.Promise, adds Future APi
>>>> class Efl.Promise.Internal, inherits from Promise, implements both
>>>> interfaces
>>>> You then create the internal one when implementing a promise and return
>>>> Owner or Future as the type (so it's an interface, which is very common
>>>> in OOP) depending on who is using them. It's a bit more complex and
>>>> doesn't add any assurance in C, but make it work as you want in bindings.
>>>
>>> i like this one much better.
>>>
>>>> With that being said, I think you are just being difficult with this
>>>> requirement. People should know not to be dumb. The same way people know
>>>> not to call eo_event_callback_call(obj, EO_EVENT_DEL, ...) on an object
>>>> randomly. They *can*, but they shouldn't. You can't protect from
>>>> everything. I think the first or second approach are just fine.
>>>
>>> the last one but you can return the core object. you don't hide the owner
>>> api's. they are there. but they are clearly FOR the OWNER to use, not the
>>> USER of the promise. it's clear. if people do stupid stuff and their code
>>> starts to not work well... well that's life. don't do that then! it's one
>>> thing what we do with an api. people can abuse it and do bad things. don't
>>> do that! all it does it make your app do bad things. it's not a good idea.
>>> we are not creating a security layer where a user must be FORCED to never
>>> be able to do anything bad and it's impossible.
>>>
>>> we just need it to be clear enough that "this api is for you to use, this
>>> other api is for some other piece of code". if it's split into 2 interfaces
>>> on the same object, then it's very clear what belongs where. :)
>>>
>>>> I also want to limit the usage. I want them to be used and proved useful
>>>> before we start using them everywhere. By useful and used, I mean useful
>>>> and used by people other than the creator. We've detected issues with
>>>> eina value, and ecore getops long after they were created although their
>>>> creators were already using them and said they were good. Same goes for
>>>> Eo, that's why we had so many iterations. I would like to have way more
>>>> proof and time before I fully commit our new API to a new unproven
>>>> concept. Eo proved useful because people were using it even when it was
>>>> hard and we told them not to. This is how much value it added to people.
>>>> Let's see if promises prove the same. Until then, I say: please, let's
>>>> not expose them in our APIs.
>>>>
>>>> I hope I haven't forgotten anything.
>>>
>>> we need time and space to experiment with them indeed. we shouldn't go
>>> gung-ho until we have worked out the kinks. i do see the usefulness of
>>> promises, but their usefulness has to beat what can be done with basic
>>> objects+events on them.
>>>
>>
>> I'm so used to fighting, I don't know how to behave at time of peace.
>> You agreed with everything I said so I don't have much to say. :P
>
> :)
>
>


------------------------------------------------------------------------------
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