summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCedric BAIL <cedric.bail@free.fr>2019-12-05 13:57:52 -0800
committerMarcel Hollerbach <mail@marcel-hollerbach.de>2019-12-11 10:36:02 +0100
commit115a9a22b1d25d8d3b2d433994cc6756174b11b9 (patch)
tree9d9af9664926db24aadd59106e99e2e138a71feb
parent6830414e95652cff4f00d79cbbc9684186081508 (diff)
eo: only forward event if someone is listening.
This limit long chain of useless event forwarding when nobody is listening at the end of the pipe. Differential Revision: https://phab.enlightenment.org/D10813
-rw-r--r--src/lib/eo/eo_base_class.c137
1 files changed, 134 insertions, 3 deletions
diff --git a/src/lib/eo/eo_base_class.c b/src/lib/eo/eo_base_class.c
index 66e6032..9fd4d2b 100644
--- a/src/lib/eo/eo_base_class.c
+++ b/src/lib/eo/eo_base_class.c
@@ -23,6 +23,18 @@ static int event_freeze_count = 0;
23 23
24typedef struct _Eo_Callback_Description Eo_Callback_Description; 24typedef struct _Eo_Callback_Description Eo_Callback_Description;
25typedef struct _Efl_Event_Callback_Frame Efl_Event_Callback_Frame; 25typedef struct _Efl_Event_Callback_Frame Efl_Event_Callback_Frame;
26typedef struct _Efl_Event_Forwarder Efl_Event_Forwarder;
27
28struct _Efl_Event_Forwarder
29{
30 const Efl_Event_Description *desc;
31 Eo *source;
32 Eo *new_obj;
33
34 short priority;
35
36 Eina_Bool inserted : 1;
37};
26 38
27struct _Efl_Event_Callback_Frame 39struct _Efl_Event_Callback_Frame
28{ 40{
@@ -41,6 +53,7 @@ typedef struct
41 Eo ***wrefs; 53 Eo ***wrefs;
42 Eina_Hash *providers; 54 Eina_Hash *providers;
43 Eina_Hash *schedulers; 55 Eina_Hash *schedulers;
56 Eina_Hash *forwarders;
44} Efl_Object_Extension; 57} Efl_Object_Extension;
45 58
46#define EFL_OBJECT_EVENT_CALLBACK(Event) Eina_Bool event_cb_##Event : 1; 59#define EFL_OBJECT_EVENT_CALLBACK(Event) Eina_Bool event_cb_##Event : 1;
@@ -124,6 +137,8 @@ typedef struct
124 if ((pd)->event_frame) (pd)->event_frame = (pd)->event_frame->next; \ 137 if ((pd)->event_frame) (pd)->event_frame = (pd)->event_frame->next; \
125} while (0) 138} while (0)
126 139
140static void _efl_event_forwarder_callback(void *data, const Efl_Event *event);
141
127static int _eo_nostep_alloc = -1; 142static int _eo_nostep_alloc = -1;
128 143
129static void 144static void
@@ -162,7 +177,8 @@ _efl_object_extension_noneed(Efl_Object_Data *pd)
162 (ext->wrefs) || 177 (ext->wrefs) ||
163 (ext->composite_parent) || 178 (ext->composite_parent) ||
164 (ext->providers) || 179 (ext->providers) ||
165 (ext->schedulers)) return; 180 (ext->schedulers) ||
181 (ext->forwarders)) return;
166 _efl_object_extension_free(pd->ext); 182 _efl_object_extension_free(pd->ext);
167 pd->ext = NULL; 183 pd->ext = NULL;
168} 184}
@@ -172,6 +188,13 @@ _efl_object_invalidate(Eo *obj_id, Efl_Object_Data *pd)
172{ 188{
173 _efl_pending_futures_clear(pd); 189 _efl_pending_futures_clear(pd);
174 190
191 if (pd->ext && pd->ext->forwarders)
192 {
193 eina_hash_free(pd->ext->forwarders);
194 pd->ext->forwarders = NULL;
195 _efl_object_extension_noneed(pd);
196 }
197
175 if (pd->ext && pd->ext->providers) 198 if (pd->ext && pd->ext->providers)
176 { 199 {
177 eina_hash_free(pd->ext->providers); 200 eina_hash_free(pd->ext->providers);
@@ -1282,6 +1305,24 @@ _special_event_count_inc(Eo *obj_id, Efl_Object_Data *pd, const Efl_Callback_Arr
1282 EO_OBJ_DONE(obj_id); 1305 EO_OBJ_DONE(obj_id);
1283 } 1306 }
1284 1307
1308 if (pd->ext && pd->ext->forwarders)
1309 {
1310 Efl_Event_Forwarder *forwarder;
1311 Eina_List *l;
1312
1313 // Check if some event need to be forwarded now
1314 EINA_LIST_FOREACH(eina_hash_find(pd->ext->forwarders, it->desc), l, forwarder)
1315 {
1316 if (!forwarder->source) continue;
1317 if (forwarder->inserted) continue;
1318 efl_event_callback_priority_add(forwarder->source,
1319 forwarder->desc,
1320 forwarder->priority,
1321 _efl_event_forwarder_callback, obj_id);
1322 forwarder->inserted = EINA_TRUE;
1323 }
1324 }
1325
1285 if (update_hash) 1326 if (update_hash)
1286 { 1327 {
1287 unsigned char event_hash; 1328 unsigned char event_hash;
@@ -2193,6 +2234,27 @@ _efl_event_forwarder_callback(void *data, const Efl_Event *event)
2193 } 2234 }
2194} 2235}
2195 2236
2237static void
2238_forwarders_list_clean(void *data)
2239{
2240 Efl_Event_Forwarder *forwarder;
2241 Eina_List *l = data;
2242
2243 EINA_LIST_FREE(l, forwarder)
2244 {
2245 if (forwarder->source)
2246 {
2247 if (forwarder->inserted)
2248 efl_event_callback_del(forwarder->source,
2249 forwarder->desc,
2250 _efl_event_forwarder_callback,
2251 forwarder->new_obj);
2252 efl_wref_del(forwarder->source, &forwarder->source);
2253 }
2254 free(forwarder);
2255 }
2256}
2257
2196EOLIAN static void 2258EOLIAN static void
2197_efl_object_event_callback_forwarder_priority_add(Eo *obj, Efl_Object_Data *pd EINA_UNUSED, 2259_efl_object_event_callback_forwarder_priority_add(Eo *obj, Efl_Object_Data *pd EINA_UNUSED,
2198 const Efl_Event_Description *desc, 2260 const Efl_Event_Description *desc,
@@ -2201,8 +2263,50 @@ _efl_object_event_callback_forwarder_priority_add(Eo *obj, Efl_Object_Data *pd E
2201{ 2263{
2202 EO_OBJ_POINTER_RETURN(new_obj, new_data); 2264 EO_OBJ_POINTER_RETURN(new_obj, new_data);
2203 EO_OBJ_DONE(new_obj); 2265 EO_OBJ_DONE(new_obj);
2266 Efl_Event_Forwarder *forwarder;
2267 Efl_Object_Extension *ext;
2268 Efl_Object_Data *dpd;
2269 Eina_List *l;
2270
2271 dpd = efl_data_scope_safe_get(new_obj, EFL_OBJECT_CLASS);
2272 EINA_SAFETY_ON_NULL_RETURN(dpd);
2273
2274 ext = _efl_object_extension_need(dpd);
2275 EINA_SAFETY_ON_NULL_RETURN(ext);
2276
2277 // Prevent double insertion for the same object source and event description
2278 EINA_LIST_FOREACH(eina_hash_find(ext->forwarders, desc), l, forwarder)
2279 {
2280 if (forwarder->desc == desc &&
2281 forwarder->new_obj == new_obj &&
2282 forwarder->source == obj)
2283 {
2284 ERR("Forwarder added on '%s' for event '%s' toward '%s' has already been set.\n",
2285 efl_debug_name_get(obj), desc->name, efl_debug_name_get(new_obj));
2286 return;
2287 }
2288 }
2289
2290 forwarder = malloc(sizeof (Efl_Event_Forwarder));
2291 EINA_SAFETY_ON_NULL_RETURN(forwarder);
2292 forwarder->desc = desc;
2293 forwarder->priority = priority;
2294 forwarder->new_obj = new_obj;
2295 efl_wref_add(obj, &forwarder->source);
2296
2297 if (efl_event_callback_count(new_obj, desc) > 0)
2298 {
2299 efl_event_callback_priority_add(obj, desc, priority, _efl_event_forwarder_callback, new_obj);
2300 forwarder->inserted = EINA_TRUE;
2301 }
2302 else
2303 {
2304 forwarder->inserted = EINA_FALSE;
2305 }
2204 2306
2205 efl_event_callback_priority_add(obj, desc, priority, _efl_event_forwarder_callback, new_obj); 2307 if (!ext->forwarders)
2308 ext->forwarders = eina_hash_pointer_new(_forwarders_list_clean);
2309 eina_hash_list_direct_append(ext->forwarders, forwarder->desc, forwarder);
2206} 2310}
2207 2311
2208EOLIAN static void 2312EOLIAN static void
@@ -2212,8 +2316,35 @@ _efl_object_event_callback_forwarder_del(Eo *obj, Efl_Object_Data *pd EINA_UNUSE
2212{ 2316{
2213 EO_OBJ_POINTER_RETURN(new_obj, new_data); 2317 EO_OBJ_POINTER_RETURN(new_obj, new_data);
2214 EO_OBJ_DONE(new_obj); 2318 EO_OBJ_DONE(new_obj);
2319 Efl_Event_Forwarder *forwarder;
2320 Efl_Object_Extension *ext;
2321 Efl_Object_Data *dpd;
2322 Eina_List *l, *tofree = NULL;
2215 2323
2216 efl_event_callback_del(obj, desc, _efl_event_forwarder_callback, new_obj); 2324 dpd = efl_data_scope_safe_get(new_obj, EFL_OBJECT_CLASS);
2325 if (!dpd) return ;
2326
2327 ext = _efl_object_extension_need(dpd);
2328 if (!ext) return ;
2329
2330 EINA_LIST_FOREACH(eina_hash_find(ext->forwarders, desc), l, forwarder)
2331 {
2332 // Remove dead source at the same time we remove any forwader
2333 if (forwarder->source == obj || forwarder->source == NULL)
2334 tofree = eina_list_append(tofree, forwarder);
2335 }
2336
2337 EINA_LIST_FREE(tofree, forwarder)
2338 {
2339 if (forwarder->source)
2340 {
2341 if (forwarder->inserted)
2342 efl_event_callback_del(obj, desc, _efl_event_forwarder_callback, new_obj);
2343 efl_wref_del(obj, &forwarder->source);
2344 }
2345 eina_hash_list_remove(ext->forwarders, desc, forwarder);
2346 free(forwarder);
2347 }
2217} 2348}
2218 2349
2219EOLIAN static void 2350EOLIAN static void