zmike pushed a commit to branch master.

http://git.enlightenment.org/core/efl.git/commit/?id=a9227fd5306ba68d020623121f3efd3f17857c76

commit a9227fd5306ba68d020623121f3efd3f17857c76
Author: Cedric Bail <[email protected]>
Date:   Thu Oct 31 13:20:52 2019 -0400

    evas: move watching over destruction of device to custom logic due to high 
use.
    
    Summary:
    This specific EFL_EVENT_DEL handler was registered thousand of time alone on
    an Evas device. Potential solution are to improve handling of this kind of 
large
    scale callback logic or just not take that path. I find it easier to have a 
custom
    code in this case to handle the destruction of Evas device and avoid this
    thousand of callback.
    
    Depends on D10492
    
    Reviewers: zmike, raster, bu5hm4n, Hermet
    
    Reviewed By: zmike
    
    Subscribers: #reviewers, #committers
    
    Tags: #efl
    
    Maniphest Tasks: T8321
    
    Differential Revision: https://phab.enlightenment.org/D10493
---
 src/lib/evas/Evas_Internal.h           |  5 ++
 src/lib/evas/canvas/efl_input_device.c | 42 +++++++++++++++
 src/lib/evas/canvas/evas_object_main.c | 98 ++++++++++++++++------------------
 src/lib/evas/include/evas_private.h    |  6 +++
 4 files changed, 99 insertions(+), 52 deletions(-)

diff --git a/src/lib/evas/Evas_Internal.h b/src/lib/evas/Evas_Internal.h
index 782742f5d9..d631cdcde5 100644
--- a/src/lib/evas/Evas_Internal.h
+++ b/src/lib/evas/Evas_Internal.h
@@ -38,6 +38,8 @@ extern "C" {
 
 #include <Efl.h>
 
+typedef struct _Evas_Object_Pointer_Data Evas_Object_Pointer_Data;
+
 EOAPI const Eina_List *efl_input_device_children_get(const Eo *obj);
 
 EOAPI void efl_input_device_evas_set(Eo *obj, Evas *e);
@@ -46,6 +48,9 @@ EOAPI Evas *efl_input_device_evas_get(const Eo *obj);
 EOAPI void efl_input_device_subclass_set(Eo *obj, Evas_Device_Subclass 
sub_clas);
 EOAPI Evas_Device_Subclass efl_input_device_subclass_get(const Eo *obj);
 
+EOAPI void efl_input_device_grab_register(Eo *obj, Efl_Canvas_Object *grab, 
Evas_Object_Pointer_Data *pdata);
+EOAPI void efl_input_device_grab_unregister(Eo *obj, Efl_Canvas_Object *grab, 
Evas_Object_Pointer_Data *pdata);
+
 typedef struct _Efl_Input_Pointer_Data  Efl_Input_Pointer_Data;
 typedef struct _Efl_Input_Key_Data      Efl_Input_Key_Data;
 typedef struct _Efl_Input_Hold_Data     Efl_Input_Hold_Data;
diff --git a/src/lib/evas/canvas/efl_input_device.c 
b/src/lib/evas/canvas/efl_input_device.c
index 607ffd5f76..52eae92cbb 100644
--- a/src/lib/evas/canvas/efl_input_device.c
+++ b/src/lib/evas/canvas/efl_input_device.c
@@ -5,6 +5,8 @@
 #include "Evas.h"
 #define EFL_INTERNAL_UNSTABLE
 #include "Evas_Internal.h"
+#include "evas_common_private.h"
+#include "evas_private.h"
 
 #define MY_CLASS EFL_INPUT_DEVICE_CLASS
 
@@ -16,6 +18,9 @@ struct _Efl_Input_Device_Data
    Eo               *evas; /* Evas */
    Efl_Input_Device *source;  /* ref */
    Eina_List        *children; /* ref'ed by efl_parent, not by this list */
+   Eina_Hash        *grabs; /* Hash of all the object that might grab this 
device.
+                               We expect thousand of them to be registered 
here,
+                               that is why we use a hash. */
    unsigned int      id;
    Efl_Input_Device_Type klass;
    unsigned int      subclass; // Evas_Device_Subclass (unused)
@@ -71,6 +76,12 @@ _efl_input_device_efl_object_destructor(Eo *obj, 
Efl_Input_Device_Data *pd)
      }
    efl_unref(pd->source);
 
+   if (pd->grabs)
+     {
+        eina_hash_free(pd->grabs);
+        pd->grabs = NULL;
+     }
+
    return efl_destructor(efl_super(obj, MY_CLASS));
 }
 
@@ -279,11 +290,42 @@ _efl_input_device_subclass_set(Eo *obj EINA_UNUSED, 
Efl_Input_Device_Data *pd,
 
 EOAPI EFL_VOID_FUNC_BODYV(efl_input_device_subclass_set, 
EFL_FUNC_CALL(sub_clas), Evas_Device_Subclass sub_clas);
 
+static void
+_grab_del(void *data)
+{
+   Evas_Object_Pointer_Data *pdata = data;
+
+   evas_object_pointer_grab_del(pdata->obj, pdata);
+}
+
+static void
+_efl_input_device_grab_register(Eo *obj EINA_UNUSED, Efl_Input_Device_Data *pd,
+                                Efl_Canvas_Object *grab, 
Evas_Object_Pointer_Data *pdata)
+{
+   if (!pd->grabs) pd->grabs = eina_hash_pointer_new(_grab_del);
+   eina_hash_add(pd->grabs, &grab, pdata);
+}
+
+EOAPI EFL_VOID_FUNC_BODYV(efl_input_device_grab_register, EFL_FUNC_CALL(grab, 
pdata),
+                          Efl_Canvas_Object *grab, Evas_Object_Pointer_Data 
*pdata);
+
+static void
+_efl_input_device_grab_unregister(Eo *obj EINA_UNUSED, Efl_Input_Device_Data 
*pd,
+                                  Efl_Canvas_Object *grab, 
Evas_Object_Pointer_Data *pdata)
+{
+   eina_hash_del(pd->grabs, &grab, pdata);
+}
+
+EOAPI EFL_VOID_FUNC_BODYV(efl_input_device_grab_unregister, 
EFL_FUNC_CALL(grab, pdata),
+                          Efl_Canvas_Object *grab, Evas_Object_Pointer_Data 
*pdata);
+
 #define EFL_INPUT_DEVICE_EXTRA_OPS                                      \
   EFL_OBJECT_OP_FUNC(efl_input_device_evas_get, _efl_input_device_evas_get), \
   EFL_OBJECT_OP_FUNC(efl_input_device_evas_set, _efl_input_device_evas_set), \
   EFL_OBJECT_OP_FUNC(efl_input_device_subclass_get, 
_efl_input_device_subclass_get), \
   EFL_OBJECT_OP_FUNC(efl_input_device_subclass_set, 
_efl_input_device_subclass_set), \
   EFL_OBJECT_OP_FUNC(efl_input_device_children_get, 
_efl_input_device_children_get), \
+  EFL_OBJECT_OP_FUNC(efl_input_device_grab_register, 
_efl_input_device_grab_register), \
+  EFL_OBJECT_OP_FUNC(efl_input_device_grab_unregister, 
_efl_input_device_grab_unregister),
 
 #include "efl_input_device.eo.c"
diff --git a/src/lib/evas/canvas/evas_object_main.c 
b/src/lib/evas/canvas/evas_object_main.c
index 27ec6e2bfc..d5b20aed22 100644
--- a/src/lib/evas/canvas/evas_object_main.c
+++ b/src/lib/evas/canvas/evas_object_main.c
@@ -81,9 +81,9 @@ _init_cow(void)
    return EINA_TRUE;
 }
 
-static Evas_Object_Pointer_Data *
-_evas_object_pointer_data_find(Evas_Object_Protected_Data *obj,
-                               Efl_Input_Device *pointer)
+Evas_Object_Pointer_Data *
+evas_object_pointer_data_find(Evas_Object_Protected_Data *obj,
+                              Efl_Input_Device *pointer)
 {
    Evas_Object_Pointer_Data *pdata;
 
@@ -95,22 +95,6 @@ _evas_object_pointer_data_find(Evas_Object_Protected_Data 
*obj,
    return NULL;
 }
 
-static void
-_evas_object_pointer_grab_del(Evas_Object_Protected_Data *obj, 
Evas_Object_Pointer_Data *pdata);
-
-static void
-_evas_device_del_cb(void *data, const Efl_Event *ev)
-{
-   Evas_Object_Protected_Data *obj;
-   Evas_Object_Pointer_Data *pdata;
-
-   obj = efl_data_scope_safe_get(data, MY_CLASS);
-   EINA_SAFETY_ON_NULL_RETURN(obj);
-   pdata = _evas_object_pointer_data_find(obj, ev->object);
-   if (!pdata) return;
-   _evas_object_pointer_grab_del(obj, pdata);
-}
-
 static void
 _evas_object_proxy_grab_del(Evas_Object_Protected_Data *obj,
                             Evas_Object_Pointer_Data *pdata)
@@ -138,9 +122,9 @@ _evas_object_proxy_grab_del(Evas_Object_Protected_Data *obj,
      }
 }
 
-static void
-_evas_object_pointer_grab_del(Evas_Object_Protected_Data *obj,
-                              Evas_Object_Pointer_Data *pdata)
+void
+evas_object_pointer_grab_del(Evas_Object_Protected_Data *obj,
+                             Evas_Object_Pointer_Data *pdata)
 {
    if ((pdata->mouse_grabbed > 0) && (obj->layer) && (obj->layer->evas))
      pdata->evas_pdata->seat->mouse_grabbed -= pdata->mouse_grabbed;
@@ -151,11 +135,12 @@ _evas_object_pointer_grab_del(Evas_Object_Protected_Data 
*obj,
         if (obj->proxy->is_proxy && obj->proxy->src_events)
           _evas_object_proxy_grab_del(obj, pdata);
      }
-   efl_event_callback_del(pdata->evas_pdata->pointer, EFL_EVENT_DEL,
-                          _evas_device_del_cb, obj->object);
-   EINA_COW_WRITE_BEGIN(evas_object_events_cow, obj->events, 
Evas_Object_Events_Data, events)
-     events->pointer_grabs = eina_inlist_remove(events->pointer_grabs, 
EINA_INLIST_GET(pdata));
-   EINA_COW_WRITE_END(evas_object_events_cow, obj->events, events);
+   if (obj->events->pointer_grabs)
+     {
+        EINA_COW_WRITE_BEGIN(evas_object_events_cow, obj->events, 
Evas_Object_Events_Data, events)
+          events->pointer_grabs = eina_inlist_remove(events->pointer_grabs, 
EINA_INLIST_GET(pdata));
+        EINA_COW_WRITE_END(evas_object_events_cow, obj->events, events);
+     }
 
    free(pdata);
 }
@@ -170,14 +155,13 @@ _evas_object_pointer_data_add(Evas_Pointer_Data 
*evas_pdata,
    EINA_SAFETY_ON_NULL_RETURN_VAL(pdata, NULL);
    pdata->pointer_mode = EVAS_OBJECT_POINTER_MODE_AUTOGRAB;
    pdata->evas_pdata = evas_pdata;
+   pdata->obj = obj;
    EINA_COW_WRITE_BEGIN(evas_object_events_cow, obj->events, 
Evas_Object_Events_Data, events)
      events->pointer_grabs = eina_inlist_append(events->pointer_grabs,
                                                 EINA_INLIST_GET(pdata));
    EINA_COW_WRITE_END(evas_object_events_cow, obj->events, events);
 
-   efl_event_callback_priority_add(evas_pdata->pointer, EFL_EVENT_DEL,
-                                   EFL_CALLBACK_PRIORITY_BEFORE,
-                                   _evas_device_del_cb, obj->object);
+   efl_input_device_grab_register(evas_pdata->pointer, obj->object, pdata);
    return pdata;
 }
 
@@ -187,7 +171,7 @@ _evas_object_pointer_data_get(Evas_Pointer_Data *evas_pdata,
 {
    Evas_Object_Pointer_Data *pdata;
 
-   pdata = _evas_object_pointer_data_find(obj, evas_pdata->pointer);
+   pdata = evas_object_pointer_data_find(obj, evas_pdata->pointer);
 
    //The pointer does not exist yet - create one.
    if (!pdata)
@@ -1068,29 +1052,39 @@ _efl_canvas_object_efl_object_invalidate(Eo *eo_obj, 
Evas_Object_Protected_Data
    evas_object_hide(eo_obj);
 
    if (obj->events)
-     EINA_COW_WRITE_BEGIN(evas_object_events_cow, obj->events, 
Evas_Object_Events_Data, events)
-       {
-          Evas_Public_Data *edata = NULL;
+     {
+        Eina_Inlist *pointer_grabs;
+
+        EINA_COW_WRITE_BEGIN(evas_object_events_cow, obj->events, 
Evas_Object_Events_Data, events)
+          {
+             Evas_Public_Data *edata = NULL;
 
-          if (!efl_invalidated_get(evas_object_evas_get(eo_obj)))
-            edata = efl_data_scope_get(evas_object_evas_get(eo_obj), 
EVAS_CANVAS_CLASS);
+             if (!efl_invalidated_get(evas_object_evas_get(eo_obj)))
+               edata = efl_data_scope_get(evas_object_evas_get(eo_obj), 
EVAS_CANVAS_CLASS);
 
-          EINA_LIST_FREE (events->focused_by_seats, dev)
-            {
-               event_id = _evas_event_counter;
-               efl_event_callback_del(dev, EFL_EVENT_INVALIDATE,
-                                      _evas_focus_device_invalidate_cb, obj);
-               if (edata) eina_hash_del_by_key(edata->focused_objects, &dev);
-               _evas_focus_dispatch_event(obj, dev, EINA_FALSE);
-               if ((obj->layer) && (obj->layer->evas))
-                 _evas_post_event_callback_call(obj->layer->evas->evas, 
obj->layer->evas, event_id);
-            }
-          EINA_INLIST_FREE(events->pointer_grabs, pdata)
-            _evas_object_pointer_grab_del(obj, pdata);
-          EINA_LIST_FREE(events->events_whitelist, dev)
-            efl_event_callback_del(dev, EFL_EVENT_DEL, 
_whitelist_events_device_remove_cb, obj);
-       }
-     EINA_COW_WRITE_END(evas_object_events_cow, obj->events, events);
+             EINA_LIST_FREE (events->focused_by_seats, dev)
+               {
+                  event_id = _evas_event_counter;
+                  efl_event_callback_del(dev, EFL_EVENT_INVALIDATE,
+                                         _evas_focus_device_invalidate_cb, 
obj);
+                  if (edata) eina_hash_del_by_key(edata->focused_objects, 
&dev);
+                  _evas_focus_dispatch_event(obj, dev, EINA_FALSE);
+                  if ((obj->layer) && (obj->layer->evas))
+                    _evas_post_event_callback_call(obj->layer->evas->evas, 
obj->layer->evas, event_id);
+               }
+             pointer_grabs = events->pointer_grabs;
+             events->pointer_grabs = NULL;
+             EINA_LIST_FREE(events->events_whitelist, dev)
+               efl_event_callback_del(dev, EFL_EVENT_DEL, 
_whitelist_events_device_remove_cb, obj);
+          }
+        EINA_COW_WRITE_END(evas_object_events_cow, obj->events, events);
+
+        EINA_INLIST_FREE(pointer_grabs, pdata)
+          {
+             pointer_grabs = eina_inlist_remove(pointer_grabs, 
EINA_INLIST_GET(pdata));
+             efl_input_device_grab_unregister(pdata->evas_pdata->pointer, 
eo_obj, pdata);
+          }
+     }
 
    event_id = _evas_object_event_new();
    evas_object_event_callback_call(eo_obj, obj, EVAS_CALLBACK_DEL, NULL, 
event_id, NULL);
diff --git a/src/lib/evas/include/evas_private.h 
b/src/lib/evas/include/evas_private.h
index 6906195db9..2081c3dc85 100644
--- a/src/lib/evas/include/evas_private.h
+++ b/src/lib/evas/include/evas_private.h
@@ -77,6 +77,7 @@ typedef struct _Evas_Format                 Evas_Format;
 typedef struct _Evas_Map_Point              Evas_Map_Point;
 typedef struct _Evas_Smart_Cb_Description_Array 
Evas_Smart_Cb_Description_Array;
 typedef struct _Evas_Smart_Interfaces_Array Evas_Smart_Interfaces_Array;
+typedef enum _Evas_Object_Intercept_Cb_Type Evas_Object_Intercept_Cb_Type;
 typedef struct _Evas_Post_Callback          Evas_Post_Callback;
 typedef struct _Evas_Coord_Touch_Point      Evas_Coord_Touch_Point;
 typedef struct _Evas_Object_Proxy_Data      Evas_Object_Proxy_Data;
@@ -1095,6 +1096,7 @@ struct _Evas_Object_Protected_State
 struct _Evas_Object_Pointer_Data {
    EINA_INLIST;
 
+   Evas_Object_Protected_Data *obj;
    Evas_Pointer_Data *evas_pdata;
    Evas_Object_Pointer_Mode pointer_mode;
    int mouse_grabbed;
@@ -1679,6 +1681,10 @@ void evas_object_inform_call_image_preloaded(Evas_Object 
*obj);
 void evas_object_inform_call_image_unloaded(Evas_Object *obj);
 void evas_object_inform_call_image_resize(Evas_Object *obj);
 void evas_object_intercept_cleanup(Evas_Object *obj);
+Evas_Object_Pointer_Data 
*evas_object_pointer_data_find(Evas_Object_Protected_Data *obj,
+                                                        Efl_Input_Device 
*pointer);
+void evas_object_pointer_grab_del(Evas_Object_Protected_Data *obj,
+                                  Evas_Object_Pointer_Data *pdata);
 void evas_object_grabs_cleanup(Evas_Object *obj, Evas_Object_Protected_Data 
*pd);
 void evas_key_grab_free(Evas_Object *obj, Evas_Object_Protected_Data *pd, 
const char *keyname, Evas_Modifier_Mask modifiers, Evas_Modifier_Mask 
not_modifiers);
 void evas_object_smart_member_cache_invalidate(Evas_Object *obj, Eina_Bool 
pass_events, Eina_Bool freeze_events, Eina_Bool source_invisible);

-- 


Reply via email to