Hi,

Honestly I'm a bit confused by the use of promise/future as the core since
ecore events aren't single-shot by definition (yes, some of them are). But
that's beyond the point for my email.


In C++ Felipe implemented eo event callbacks like this:
  event_add(event_type, object, functor);

functor is an object containing the context data and the function pointer.
It's quite likely to be std::bind() of a lambda only defined in the above
line.
So it's not accessible for deletion later. The solution being to keep a
handle on the connection:
  signal_connection sig = event_add(event_type, object, functor);
  // keep sig somewhere, and later:
  sig.disconnect();

For basic function callbacks (eg. Format_Func_Cb) I think this is not an
issue as there is only one slot. Just pass null to reset it. But ecore
events can have multiple listeners.

So, I think that if we want to design a generated EO API for ecore events
from the ground up, we need to keep in mind that only C will be able to
call event_del() with a C function pointer directly.



On Fri, Nov 24, 2017 at 9:42 AM, Carsten Haitzler <[email protected]>
wrote:

> On Thu, 23 Nov 2017 10:12:40 -0200 Gustavo Sverzut Barbieri
> <[email protected]> said:
>
> > my proposal on this whole topic is a bit different and hopefully simpler:
> >
> > - one time, single shot (ecore jobs): reimplement as promises/future.
> > currently they are done on top of events (to avoid changing the
> > ecore_main.c), of course this needs to be reversed. Simple and clean.
> > Just need core changes, since efl_loop_job() returns a future already.
>
> something has to queue them to be handled later anyway... so it'd need that
> "event queue" mechanism to use/build on.
>
> > - broadcast events: use Eo as below:
> >
> >    * no "event type", just event object (which as its Efl_Class, of
> course);
>
> that was the idea. you allocate a new event type (get an int or handle).
> you
> then GET the event type object from the loop, then listen to "event"
> callback
> on it. same one on every event type object. the object "represents" the
> event
> type. since events can be posted multiple times and are not one-off,
> futures
> don't really apply.
>
> >    * Future efl_loop_receive_once(loop, Efl_Class event_class); // or
> > better name to "receive broadcast only once"
>
> i don't think the event queue is the place for this. if you want a one-off
> call
> for an action you do now in the future, then return that at the time you
> make
> the call from the action. this may use the event queue underneath as an
> event
> bus, but the only thing that is like this in ecore that builds on top of
> the
> queue are jobs.
>
> >    * efl_loop_receiver_add(loop, Efl_Class event_class, cb, data); //
> > or better name to "add broadcast receiver, like event cb"
> >    * efl_loop_receiver_del(loop, Efl_Class event_class, cb, data); //
> > or better name to "del broadcast receiver, like event cb"
> >    * efl_loop_broadcast(loop, event_object);
> >
>

I like the idea of having only a Class as handle.


>
> close to what i was thinking. i was more thinking:
>
> // called once ever in an application:
> Efl_Loop_Event_Type efl_loop_event_type_new(Eo *loop, MY_EVENT_INFO_CLASS);
> // called to get the object representing that event type for that loop
> Eo *efl_loop_event_get(Eo *loop, Efl_Loop_Event_Type type);
>
> // to listen to an event:
> event_type_obj = efl_loop_event_get(loop, event_type_id);
> efl_event_callback_add(event_type_obj, EFL_LOOP_EVENT_TRIGGERED, mycall,
> data);
>
> // to post an event:
> Eo *event_obj = my_event_info_event_new(event_type_obj);
> efl_event_type_post(event_type_obj, event_obj);
>
> every event type want you to create a class to represent it (they all must
> inherit a base event type class). the event type object is a factory that
> produces event objects (this means it also can act as a cache for them via
> del
> intercepts for example). the factory produces event objects of some
> specific
> type based on the class you define. you can fill in the obj with
> appropriate
> data at creation time, then when ready, post the event to the loop by the
> standard "post" method that is in the event type class. since the event
> type
> object knows what loop it belongs to, it will post to its owning loop. some
> time later as this queue is processed, the triggered event callback will be
> called per object in the queue.
>
> > Then internally:
> >
> >
> >    // efl_loop_receive_once()
> >    loop->receivers[event_class]:  hash class -> array of promises to
> resolve.
> >    promise = eina_promise_new(...);
> >    future = efl_future_then(loop, eina_future_new(promise)); // use
> > efl variant to auto-delete future if loop dies!
> >    loop->receivers[event_class].append(promise);
> >    return future;
>
> i dislike this for reasons above. the promises are really the domain of the
> "action" to create and handle. the event queue is just s pub/sub bus.
> one-off's
> are what jobs are for. we already have efl_loop_job's for just this and
> they
> are promises/futures. they need some deferring/event queue mechanism to
> live on
> top of. they currently depend on the legacy ecore jobs which depend on
> the legacy event queue. that is the thing i need to replace. i consider
> jobs
> (one-off events) a solved problem other than replacing the use of of the
> legacy
> ecore event and job api's inside the code. :)
>
> >    // efl_loop_broadcast()
> >    event_class = efl_class_get(event);
> >    foreach promise of loop->receivers[event_class] {
> >       eina_promise_resolve(promise, eina_value_object_init(event)); //
> > auto-refs!
> >    }
> >    loop->receivers[event_class].clear(); // empty array. recurring
> > will re_schedule
> >
> >
> >
> >    // efl_loop_receiver_add()
> >    future = efl_loop_receive_once(...); // use same core
> >
> >    // keep info to re-schedule and "del" (unregister)
> >    ctx = alloc({ .event_class = event_class, .cb = cb, .data = data });
> >    loop->receivers.append(ctx); // or loop->receivers[event_class].
> append
> > (ctx);
> >
> >    future2 = eina_future_then(future, re_schedule, ctx); // future
> > chain that auto re-schedules and calls user
> >    ctx->future = future2;
> >
> >
> >   // efl_loop_receiver_del()
> >   foreach ctx of loop->receivers {  // or loop->receivers[event_class]
> >      if (ctx->event_class == event_class && ctx->cb == cb && ctx->data
> > == data) {
> >         efl_future_cancel(ctx->future);
> >         loop->receivers.remove(ctx);
> >         free(ctx);
> >         return true;
> >      }
> >   }
> >   return false; // not found
> >
> >
> > Advantages:
> >
> >   - very simple to implement, basically invert Promise/Future <->
> > Ecore_Event handling in existing main loop;
> >
> >  - Job is natively handled (since it's a promise/future in the new api);
> >
> >  - single shot events are the core, very easy to manage
> >
> >  - recurring events are done on top of single shot, adds one more cb,
> > but no big deal in performance (if it's, just reverse the structures)
> >
> >  - events as proper Eo objects: give us many possibilities without
> > need to implement extras, like references, methods (getters, protected
> > setters)...
> >
> > I'd not go with Eina_Value as events. It could be done, would work
> > exactly the same but offers less flexibility (needs copy intead of ref
> > count, no way to protect members). But if Eo is considered too heavy
> > or cumbersome, it could be used. (cumbersome: remember eolian should
> > help!)
> >
> > For Eina_Value_Type, special care would be needed for structures...
> > I'm not expecting users to create new Eina_Value_Type for each event,
> > rather just use EINA_VALUE_TYPE_STRUCT or similar. In these cases,
> > "subtype" is needed, that describes the structure itself (it can be
> > used as event_class). Or impose it's always a structure and in this
> > case pass the Eina_Value_Struct_Desc instead of Eina_Value_Type as
> > "event_class".
>
> eina value might be another option for the event object to be posted, but i
> kind of leaned to the heavier eo objects... because i know it's what we do
> for
> input events already and it can be optimized as above to be less costly.
>
> > On Wed, Nov 22, 2017 at 5:38 AM, Jean-Philippe André <[email protected]>
> > wrote:
> > > Hi,
> > >
> > > I talked to raster for clarification.
> > >
> > > 2017-11-22 14:57 GMT+09:00 Carsten Haitzler <[email protected]>:
> > >
> > >> So we had a partly done move to efl_loop. it still was all built on
> top of
> > >> the
> > >> main loop globals. If this is all done right then we can have multiple
> > >> loops
> > >> (e.g. one per thread) and that is a good thing.
> > >>
> > >> So I've been fixing that. I've done just about all the globals in
> ecore
> > >> EXCEPT
> > >> ecore events. I now have to think about how to do this in
> eo/interfaces
> > >> with
> > >> efl loop objects and so on. I'm mulling how to do it.
> > >>
> > >> We still have some need for a deferred event bus/queue. A lot of
> things
> > >> that
> > >> are ecore events should be callbacks on objects directly and that's
> being
> > >> fixed, but an event queue + types is still needed.
> > >>
> > >> So there are a few aspects to this.
> > >>
> > >> 1. Creating of new event types at runtime (and allocating a unique
> > >> identifier
> > >> for them).
> > >> 2. Being able to submit them to a queue to be "processed later"
> > >> 3. Being able to call callbacks that are listening for that type of
> event
> > >> and
> > >> hand them the deferred event data.
> > >>
> > >> This is used as the backing for ecore_jobs and pretty much every i/o
> thing
> > >> (input events, i/o and more) as well as in-process custom event
> bus+events.
> > >>
> > >> My current thought is this.
> > >>
> > >> 1. event types are still ints with a single global shared backing
> table of
> > >> all
> > >> event types (allocated once ever much like atoms in x).
> > >> 2. event event is an eo object on the queue (of some type).
> > >> 3. some event object "factory" on the loop that creates and "deletes"
> > >> (caches
> > >> then) these event objects for recycling.
> > >>
> > >> Does anyone have better ideas? I considered the event type being an
> object
> > >> itself and also doubling as a factory per event type but due to
> multiple
> > >> threads you'd probably be creating an object then per thread per event
> > >> type and
> > >> I do not like that.
> > >
> > >
> > >
> > > Basically we have two base EO types:
> > >
> > >  - "ecore event type" EO class:
> > > singleton per loop, it's a handle
> > > you can request the loop for the handle  given the UUID
> > > contains the read-only UUID, maybe a string description, and an EO
> event
> > > "received" or whatever
> > > created and managed by the Efl.Loop (each Loop would need to create
> their
> > > own handles)
> > > listeners add an EO callback for "received" to that handle, this keeps
> the
> > > listeners list per loop
> > > the loop has a special function to send an event
> > >
> > >  - "ecore event info" EO class:
> > > an ecore event that carries no info could even use null
> > > event info is a base class with a link to its type
> > > the loop creates and manages these temporary objects as events are
> being
> > > processed
> > >
> > >
> > > This is consistent with input events (info type are EO objects with a
> > > common base class).
> > > I see no major issue with this design, besides extra memory
> requirements.
> > >
> > > --
> > > Jean-Philippe André
> > > ------------------------------------------------------------
> ------------------
> > > 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
> >
> >
> >
> > --
> > Gustavo Sverzut Barbieri
> > --------------------------------------
> > Mobile: +55 (16) 99354-9890
> >
> > ------------------------------------------------------------
> ------------------
> > 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
>
>
> --
> ------------- 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
>



-- 
Jean-Philippe André
------------------------------------------------------------------------------
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