On Thu, 1 Mar 2018 14:11:26 -0300 Gustavo Sverzut Barbieri <[email protected]>
said:

> On Wed, Feb 28, 2018 at 2:33 AM, Carsten Haitzler <[email protected]>
> wrote:
> > On Tue, 27 Feb 2018 18:34:59 -0500 Cedric Bail <[email protected]> said:
> >
> >> -------- Original Message --------
> >>  On February 27, 2018 2:52 PM, Carsten Haitzler <[email protected]>
> >> wrote:
> >>
> >> >so I'm implementing a new efl.exe class (and efl.task and some others)
> >> >and i
> >> > WAS going to use a future as the return for run() ... but after just
> >> > writing about 20 lines of code (get a scheduler, create a promise alloc
> >> > promise data and all the checking in between) and i then realized...
> >> > it's ballooning to an insane amount of code vs event_callback_call which
> >> > is a 1 line func call when the event happens.
> >> >
> >> > let me just copy and paste the relevant lines i had sketched out (was not
> >> > final or even compiling yet):
> >> >
> >> > typedef struct _Efl_Exe_Run_Data
> >> > {
> >> > Eo *obj;
> >> > } Efl_Exe_Run_Data;
> 
> not sure you need this

i need to report the object the future is for with the future... and i don't
want to rely on people having to use the data ptr for that. this is probably
one of the most common needs/uses of a future - that it's a one off action FOR
an object.

> >> > static void
> >> > _efl_exe_run_cancel(void *data, const Eina_Promise *dead_ptr EINA_UNUSED)
> >> > {
> >> > Efl_Exe_Run_Data *d = data;
> >> >
> >> > efl_task_end(d->obj);
> >> >}
> >> >
> >> > Efl_Exe_Run_Data *d;
> >> > Eina_Promise *p;
> >> >
> >> > d = calloc(1, sizeof(Efl_Exe_Run_Data));
> >> > EINA_SAFETY_ON_NULL_RETURN_VAL(d, NULL);
> >> > d->obj = obj;
> >> >p = eina_promise_new(sched, _efl_exe_run_cancel, d);
> >> > EINA_SAFETY_ON_NULL_RETURN_VAL(p, NULL);
> >> > d->promise = p;
> >> >d->run_future = efl_future_Eina_FutureXXX_then(obj, eina_future_new(p));
> >> >return d->run_future;
> >>
> >> You do not need to keep the future at all in your structure. You are good
> >> to go with just :
> >>
> >> return efl_future_Eina_FutureXXX_then(obj, eina_future_new(p));
> >
> > then how do i trigger success or failure of the future if i don't have a
> > handle on it - well promise/future... whatever. same thing to me. i dislike
> > the whole division of promise vs future. to me it's an async task that at
> > some point in the future triggers a success or failure then disappears
> > after that.
> 
> you just keep the write/send side: Eina_Promise: p... that's where you
> send your results.

well i need to keep a handle to something. that's my point.

> >> And once we have migrate future<> in .eo to Eina_Future, it will become
> >> just :
> >>
> >> return eina_future_new(p);
> >
> > still have to store it in the object to trigger it and pass in results like
> > exit codes ... or object handles. and as below. i can't pass an obj handle
> > via an eina_value. :( the caller has to remember to pass in the obj as the
> > data ptr... not very nice compared to events that always give you the obj
> > the event happened on.
> 
> you can, there is an EO: EINA_VALUE_TYPE_OBJECT, it's juste declared
> down in the stack:
> 
> https://git.enlightenment.org/core/efl.git/tree/src/lib/eo/Eo.h#n2049

you're right. i was looking in the eina_value headers. not in eo headers.

> >> > // XXX: no eina value for eo obj handles... :( call where exe exit
> >> > handled Eina_Value *val = eina_value_new(EINA_VALUE_TYPE_UINT64);
> >> > eina_promise_resolve(d->run_future, val);
> >>
> >> This line can be properly written as :
> >> eina_promise_resolve(d->promise, eina_value_uint_init(ret));
> >
> > errr... but i want to pass an object to the promise, not an int...
> 
>    eina_value_object_init(obj)
> 
> 
> >> > i got to 22 lines and i wasn't even done yet (need to do some more
> >> > housekeeping)... vs 1 line for event_callback_call. i'm going with events
> >> > until futures/promises are not a crazy amount of code compared to events.
> >> > this is it with events:
> >> >
> >> > efl_event_callback_call(obj, EFL_TASK_EVENT_EXIT, NULL);
> >>
> >> This is absolutely not doing what the future code is doing. You are not
> >> detecting when a user has removed the handler and so call efl_task_end
> >> accordingly. You are also not sending a structure with the exit code either
> >
> > i don't need to send the data in a future - it's stored on the object
> > anyway. you pick it up with a get from the object.
> 
> well, that's misuse of the promise result... if you're running
> something to get data, that's what you should get at the end, not the
> object...

the object represents the execution of that task (exe) d it survives the
death of the exe or thread until its voluntarily deleted so data can be
retrieved from it "at leisure". i don't think storing this data on the object
is wrong at all because it does need to exist somewhere and storing it here is
far more convenient. it's not transient data. it doesn't keep changing like
i/o. it's stored once and stays.

> if the user needs the object, he can pass that as his future cb data.

i disagree with this. the data should be THEIR data, not the object. since the
object has to be deleted on exit or some point after that, the object is needed
pretty much, so why use up the only data ptr just for that when its a necessity?

no. we can't auto-del the object no matter how much i'd love to. felipe would
kill me. :) ... 

> the idea is that these things can be chained, including transformations...
> like:
> 
>   bla.run().then(uppercase).then(console.log)
> 
> we even offer some converters and a console future for such things.
> Actually we should even do more,
> like those exposed by http://reactivex.io, handling multiple wait,
> debounce, etc.

i know what they are for. :)

> > oooh... no no no. first - i don;t need know now if the handler has been
> > added or removed because callback_call handles that for me.
> > and calling end() sent a
> > signal to the child process to request it to end... it does not mean it has
> > ended yet. so you would never sensibly call end from the exit event cb
> > because that's sending end to a process that no longer exists... just the
> > object representing it does still to store the results.
> >
> > so maybe you mean "del()" the object if the caller isn't listening for exit
> > events... It'd LOVE to do that, but c++ people will hate autodel... which is
> > exactly what that would be.
> 
> well, that's exactly what the promise does, and to consider "match
> behavior", that's what you should do.

the promise is deleted.. the exe etc. object cant be. and that object has to
stay around because you need long term control like sending term/kill signals
or handling i/o to and from it.

> usually with regular events we'd just "forget" about it and leave the
> task running, doing its process without cancelling... which is bad
> most of the time.

yes. that's why the object stays - it's not just a simple promise that fails or
succeeds. there is an exit code, there is i/o etc. ...

in theory if you don't care about the results you could delete the exe or even
thread obj and thus lose your connection to it and control lines... but then
never get a result. :)

> >> (and of course you are not describing it in the .eo file). I don't even see
> >> how you can compare this two lines ? And we are not even looking at the
> >> user of the API here which is what matter even more. How do you make sure
> >> that the event is always delivered properly ? How often do you generate
> >> the event (Every time someone register a callback) ? There is a lot of
> >> open question with this kind of API that you are just disregarding here.
> >
> > it's called when the parent process knows the child has exited and what the
> > exit code is. there is no guarantee this happens during the life of the
> > object at all. the process could become hung on a kernel syscall and never
> > exit, ever. that's what the exit event is. when this happens. it's
> > guaranteed to be called when this event occurs.
> >
> > my point is the event is 1 line. futures is a massive blob of code to
> > achieve the same goal. i find them basically unusable to the point that i'm
> > just avoiding them now. if they were "1 liners" too... then great. but they
> > are not. (well they will be a line to create and store, a line in a
> > destructor to cancel on destruction if still there and another line in the
> > "where the event happens" to either call success or failure with the future
> > data... but it needs to be far far far simpler than it is.
> 
> you just realize that the code is always the same, right? there is no
> magic, we're just doing something on behalf of users, in a clear and
> standard way.

ummm it's not the same. its far longer. even if its half of what i described
it's still far longer than an event.

> so yes, you're doing bit more work so users don't have to. Like
> keeping references, canceling, etc. Our hope is that core devs (that
> usually deal with eina_promise part) will be more careful with
> managements and the likes.

a LOT more work. and the user doesn't do less.they still have to provide a
function to call on exit.

> users just pass one callback and *always* get called (even with "ECANCELED").
> 
> as for "lines of code", for sure we could offer a way to "add a
> promise to this object", it would fetch the "loop" from a loop-user,
> then fetch the scheduler... then create the promise and return.

that's my point. that isn't there. and promises/futures code is just a hairball
that figuring out how to add it is not something i want to spend time on. i've
already fixed some things there, but i have gotten to the point where i now am
going to work around them instead. i am not even using the timeout futures
anymore as they crash (i decided to set null to the content to try and catch it
more easily rather than have junk)...

they are just not worth the pain IMHO as it stands.

> the "cancel the promise" part is already done by the efl_future (note:
> "EFL", not "EINA"), which binds the future/promise to the object
> life... on destruction they are automatically cleared. As Cedric said,
> once old efl_future dies and Eolian gets future<x> mapping, this will
> be generated for you.

it's not there. it's not documented that well and certainly doesn't have the
helpers needed like above, and minimal good examples that are concise and
simple.

so either make futures sane and sensible to use from within efl, or give up. i
certainly am not writing a huge blob of code every time a future needs to be
used. efl wax created originally to serve enlightenment and it's needs. e is in
c. associated needs are too. futures do not make things simpler or easier
there. it's some nicer syntax sugar in js etc. ... but this is just making code
harder to use and worse for ourselves in the name of a currently non-existent
js usersbase. if it came with "minimal effort beyond events" then fine. support
this theoretical userbase and maybe it might happen. it's not minimal. that is
my point. i don't see it moving anywhere either at this point. :(

-- 
------------- Codito, ergo sum - "I code, therefore I am" --------------
Carsten Haitzler - [email protected]


------------------------------------------------------------------------------
Check out the vibrant tech community on one of the world's most
engaging tech sites, Slashdot.org! http://sdm.link/slashdot
_______________________________________________
enlightenment-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/enlightenment-devel

Reply via email to