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
