summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarcel Hollerbach <mail@marcel-hollerbach.de>2020-08-05 10:45:29 +0200
committerMarcel Hollerbach <mail@marcel-hollerbach.de>2020-08-06 10:34:31 +0200
commit3d547a0b06c5932d40fa0b12c32224fce5937652 (patch)
tree46f17d29d9b7cd8891e6d7895f9e22071ad75733
parent3f4bcd02dc72701a686af602210c1ad13aef0f7f (diff)
eo: event callback call optimization
a little overfiew to how eos event emission is working: - In eo there are 2 types of events restart events and normal events. Normals are *always* emitted from callback_max to 0 Restarts are emitted from the previous emissions current idx to 0. The previous emission will stop then - To keep track of the previous event emissions for restarts there was an eina inlist. - To keep track of other things in eo, there was an additional eo event stack frame (newly inserted events etc. etc.) This commit now uses this event stack frame for implementing the details about the restart events. This has the advatage that every efl_object_data contains one byte less, and the up to date keeping of the id's in the restart infrastructure is not needed anymore, making the whole event emission code less instructions and faster. How this now works: - Every emission has a event emission frame, when the emission starts, the frame is added, next points to the next older event emission. In this event stack frame we are storing the current idx, the description and a few other things that are not really relevant at this point. - when a restart event is started, this event stack is searched from the current frame up to the next one featuring the same event description. The event frame stack is then remembered, if the event emission is done, the current idx (normally 0 or something higher when callback was stopped) is then copyied back to the earlier frame. - Based on the nature of the event frame stacks, the idx is updated every iteration. And for the restart events, we only need to know the next, which removes the need of permanently updating the idx in the current stack. - The event frame stack is not allocated on the heap, hence more things in there does not matter at all. Reviewed-by: Cedric BAIL <cedric.bail@free.fr> Differential Revision: https://phab.enlightenment.org/D12097
-rw-r--r--src/lib/eo/eo_base_class.c61
1 files changed, 21 insertions, 40 deletions
diff --git a/src/lib/eo/eo_base_class.c b/src/lib/eo/eo_base_class.c
index 565f4805e8..8132bcea58 100644
--- a/src/lib/eo/eo_base_class.c
+++ b/src/lib/eo/eo_base_class.c
@@ -38,6 +38,7 @@ struct _Efl_Event_Forwarder
38 38
39struct _Efl_Event_Callback_Frame 39struct _Efl_Event_Callback_Frame
40{ 40{
41 const Efl_Event_Description *desc;
41 Efl_Event_Callback_Frame *next; 42 Efl_Event_Callback_Frame *next;
42 unsigned int idx; 43 unsigned int idx;
43 unsigned int inserted_before; 44 unsigned int inserted_before;
@@ -65,8 +66,6 @@ struct _Efl_Object_Data
65 66
66 Efl_Object_Extension *ext; 67 Efl_Object_Extension *ext;
67 68
68 Eina_Inlist *current;
69
70 Efl_Event_Callback_Frame *event_frame; 69 Efl_Event_Callback_Frame *event_frame;
71 Eo_Callback_Description **callbacks; 70 Eo_Callback_Description **callbacks;
72#ifdef EFL64 71#ifdef EFL64
@@ -2035,11 +2034,12 @@ _event_callback_call(Eo *obj_id, Efl_Object_Data *pd,
2035 Eina_Bool legacy_compare) 2034 Eina_Bool legacy_compare)
2036{ 2035{
2037 Eo_Callback_Description **cb; 2036 Eo_Callback_Description **cb;
2038 Eo_Current_Callback_Description *lookup, saved; 2037 Efl_Event_Callback_Frame *restart_lookup = NULL; //a pointer to a frame, which is high up the stack, which we use to restore
2039 Efl_Event ev; 2038 Efl_Event ev;
2040 unsigned int idx; 2039 unsigned int idx;
2041 Eina_Bool callback_already_stopped, ret; 2040 Eina_Bool callback_already_stopped, ret;
2042 Efl_Event_Callback_Frame frame = { 2041 Efl_Event_Callback_Frame frame = {
2042 .desc = desc,
2043 .next = NULL, 2043 .next = NULL,
2044 .idx = 0, 2044 .idx = 0,
2045 .inserted_before = 0, 2045 .inserted_before = 0,
@@ -2069,7 +2069,6 @@ _event_callback_call(Eo *obj_id, Efl_Object_Data *pd,
2069 2069
2070 EVENT_STACK_PUSH(pd, &frame); 2070 EVENT_STACK_PUSH(pd, &frame);
2071 2071
2072 lookup = NULL;
2073 callback_already_stopped = pd->callback_stopped; 2072 callback_already_stopped = pd->callback_stopped;
2074 pd->callback_stopped = EINA_FALSE; 2073 pd->callback_stopped = EINA_FALSE;
2075 ret = EINA_TRUE; 2074 ret = EINA_TRUE;
@@ -2109,9 +2108,6 @@ restart_back:
2109 (event_freeze_count || pd->event_freeze_count)) 2108 (event_freeze_count || pd->event_freeze_count))
2110 continue; 2109 continue;
2111 2110
2112 // Handle nested restart of walking list
2113 if (lookup) lookup->current = idx - 1;
2114
2115 it->func((void *) (*cb)->func_data, &ev); 2111 it->func((void *) (*cb)->func_data, &ev);
2116 /* Abort callback calling if the func says so. */ 2112 /* Abort callback calling if the func says so. */
2117 if (pd->callback_stopped) 2113 if (pd->callback_stopped)
@@ -2119,10 +2115,6 @@ restart_back:
2119 ret = EINA_FALSE; 2115 ret = EINA_FALSE;
2120 goto end; 2116 goto end;
2121 } 2117 }
2122 // We have actually walked this list during a nested call
2123 if (lookup &&
2124 lookup->current == 0)
2125 goto end;
2126 } 2118 }
2127 } 2119 }
2128 else 2120 else
@@ -2133,9 +2125,6 @@ restart_back:
2133 (event_freeze_count || pd->event_freeze_count)) 2125 (event_freeze_count || pd->event_freeze_count))
2134 continue; 2126 continue;
2135 2127
2136 // Handle nested restart of walking list
2137 if (lookup) lookup->current = idx - 1;
2138
2139 (*cb)->items.item.func((void *) (*cb)->func_data, &ev); 2128 (*cb)->items.item.func((void *) (*cb)->func_data, &ev);
2140 /* Abort callback calling if the func says so. */ 2129 /* Abort callback calling if the func says so. */
2141 if (pd->callback_stopped) 2130 if (pd->callback_stopped)
@@ -2143,23 +2132,19 @@ restart_back:
2143 ret = EINA_FALSE; 2132 ret = EINA_FALSE;
2144 goto end; 2133 goto end;
2145 } 2134 }
2146 // We have actually walked this list during a nested call
2147 if (lookup &&
2148 lookup->current == 0)
2149 goto end;
2150 } 2135 }
2151 } 2136 }
2152 idx += frame.inserted_before; 2137 /*
2138 * copy back the idx that might have changed due to restarts, (theoretically only needed with restarts, condition made everything slower)
2139 * additionally adjust to event subscriptions that have been added in a event callback
2140 */
2141 idx = frame.idx + frame.inserted_before;
2153 frame.inserted_before = 0; 2142 frame.inserted_before = 0;
2154 } 2143 }
2155 2144
2156end: 2145end:
2157 // Handling restarting list walking complete exit. 2146 // Handling restarting list walking complete exit.
2158 if (lookup) lookup->current = 0; 2147 if (restart_lookup) restart_lookup->idx = 0;
2159 if (lookup == &saved)
2160 {
2161 pd->current = eina_inlist_remove(pd->current, EINA_INLIST_GET(lookup));
2162 }
2163 2148
2164 EVENT_STACK_POP(pd); 2149 EVENT_STACK_POP(pd);
2165 2150
@@ -2169,26 +2154,22 @@ end:
2169 2154
2170 return ret; 2155 return ret;
2171restart: 2156restart:
2172 EINA_INLIST_FOREACH(pd->current, lookup) 2157 // Search for the next frame that has the same event description
2158 for (restart_lookup = frame.next; restart_lookup; restart_lookup = restart_lookup->next)
2173 { 2159 {
2174 if (lookup->desc == desc) break; 2160 if (restart_lookup->desc == desc) break;
2175 } 2161 }
2176 2162
2177 // This is the first event to trigger it, so register it here 2163 // Ensure that the idx is the next from the previous run, minimum number 0
2178 if (!lookup) 2164 if (restart_lookup) {
2179 { 2165 idx = restart_lookup->idx - 1;
2180 // This following trick get us a zero allocation list 2166 } else {
2181 saved.desc = desc; 2167 idx = 0;
2182 saved.current = 0; 2168 }
2183 lookup = &saved; 2169 // If this is 0, then we are restarting
2184 // Ideally there will most of the time be only one item in this list 2170 if (!idx)
2185 // But just to speed up things, prepend so we find it fast at the end 2171 idx = pd->callbacks_count;
2186 // of this function
2187 pd->current = eina_inlist_prepend(pd->current, EINA_INLIST_GET(lookup));
2188 }
2189 2172
2190 if (!lookup->current) lookup->current = pd->callbacks_count;
2191 idx = lookup->current;
2192 goto restart_back; 2173 goto restart_back;
2193} 2174}
2194 2175