summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJeeyong Um <conr2d@gmail.com>2017-03-24 16:26:36 +0900
committerJeeyong Um <conr2d@gmail.com>2017-03-24 16:26:36 +0900
commitb2d05b3cd71fd91fde94c31c9779276f107d7163 (patch)
treec8cbc63590f326f8e0b9ac08e2142ffa0952759a
parent4c419498f22498ad3458c681d2969289c1348484 (diff)
Efl.Observable: Delay deletion of inner list not to break iterationdevs/conr2d/observer
-rw-r--r--src/lib/efl/interfaces/efl_observer.c57
1 files changed, 43 insertions, 14 deletions
diff --git a/src/lib/efl/interfaces/efl_observer.c b/src/lib/efl/interfaces/efl_observer.c
index 9316529ba3..716d086a8f 100644
--- a/src/lib/efl/interfaces/efl_observer.c
+++ b/src/lib/efl/interfaces/efl_observer.c
@@ -4,6 +4,8 @@
4typedef struct 4typedef struct
5{ 5{
6 Eina_Hash *observers; 6 Eina_Hash *observers;
7 int walking;
8 Eina_List *pending_deletion;
7} Efl_Observable_Data; 9} Efl_Observable_Data;
8 10
9typedef struct 11typedef struct
@@ -62,10 +64,26 @@ _observer_del(Eo *obj EINA_UNUSED, Efl_Observable_Data *pd, Efl_Observer_List *o
62 observers->list = eina_list_remove_list(observers->list, target); 64 observers->list = eina_list_remove_list(observers->list, target);
63 65
64 if (!observers->list) 66 if (!observers->list)
65 eina_hash_del(pd->observers, observers->key, observers); 67 {
68 if (!pd->walking)
69 eina_hash_del(pd->observers, observers->key, observers);
70 else
71 pd->pending_deletion = eina_list_append(pd->pending_deletion, observers);
72 }
66 } 73 }
67} 74}
68 75
76static void
77_process_deletion(Eo *obj EINA_UNUSED, Efl_Observable_Data *pd)
78{
79 if (!pd || pd->walking) return;
80
81 Efl_Observer_List *observers;
82
83 EINA_LIST_FREE(pd->pending_deletion, observers)
84 eina_hash_del(pd->observers, observers->key, observers);
85}
86
69EOLIAN static void 87EOLIAN static void
70_efl_observable_efl_object_destructor(Eo *obj, Efl_Observable_Data *pd) 88_efl_observable_efl_object_destructor(Eo *obj, Efl_Observable_Data *pd)
71{ 89{
@@ -94,6 +112,8 @@ _efl_observable_observer_add(Eo *obj EINA_UNUSED, Efl_Observable_Data *pd, const
94 observers->key = eina_stringshare_add(key); 112 observers->key = eina_stringshare_add(key);
95 eina_hash_direct_add(pd->observers, observers->key, observers); 113 eina_hash_direct_add(pd->observers, observers->key, observers);
96 } 114 }
115 else if (!observers->list)
116 pd->pending_deletion = eina_list_remove(pd->pending_deletion, observers);
97 117
98 or = eina_list_search_sorted(observers->list, _search_cb, obs); 118 or = eina_list_search_sorted(observers->list, _search_cb, obs);
99 if (!or) 119 if (!or)
@@ -105,9 +125,7 @@ _efl_observable_observer_add(Eo *obj EINA_UNUSED, Efl_Observable_Data *pd, const
105 observers->list = eina_list_sorted_insert(observers->list, _insert_cb, or); 125 observers->list = eina_list_sorted_insert(observers->list, _insert_cb, or);
106 } 126 }
107 else 127 else
108 { 128 EINA_REFCOUNT_REF(or);
109 EINA_REFCOUNT_REF(or);
110 }
111} 129}
112 130
113EOLIAN static void 131EOLIAN static void
@@ -133,16 +151,15 @@ _efl_observable_observer_clean(Eo *obj EINA_UNUSED, Efl_Observable_Data *pd, Efl
133 151
134 it = eina_hash_iterator_data_new(pd->observers); 152 it = eina_hash_iterator_data_new(pd->observers);
135 EINA_ITERATOR_FOREACH(it, observers) 153 EINA_ITERATOR_FOREACH(it, observers)
136 { 154 _observer_del(obj, pd, observers, eina_list_search_sorted_list(observers->list, _search_cb, obs));
137 _observer_del(obj, pd, observers, eina_list_search_sorted_list(observers->list, _search_cb, obs));
138 }
139 eina_iterator_free(it); 155 eina_iterator_free(it);
140} 156}
141 157
142typedef struct 158typedef struct
143{ 159{
144 Eina_Iterator iterator; 160 Eina_Iterator iterator;
145 Eina_Iterator *classes; 161 Eina_List *current;
162 Eina_List *next;
146} Efl_Observer_Iterator; 163} Efl_Observer_Iterator;
147 164
148static Eina_Bool 165static Eina_Bool
@@ -151,9 +168,14 @@ _efl_observable_observers_iterator_next(Eina_Iterator *it, void **data)
151 Efl_Observer_Iterator *et = (void *)it; 168 Efl_Observer_Iterator *et = (void *)it;
152 Efl_Observer_Refcount *or = NULL; 169 Efl_Observer_Refcount *or = NULL;
153 170
154 if (!eina_iterator_next(et->classes, (void **)&or)) return EINA_FALSE; 171 if (!et->current) return EINA_FALSE;
172
173 or = eina_list_data_get(et->current);
155 if (!or) return EINA_FALSE; 174 if (!or) return EINA_FALSE;
156 175
176 et->current = et->next;
177 et->next = eina_list_next(et->current);
178
157 *data = or->o; 179 *data = or->o;
158 180
159 return EINA_TRUE; 181 return EINA_TRUE;
@@ -170,7 +192,6 @@ _efl_observable_observers_iterator_free(Eina_Iterator *it)
170{ 192{
171 Efl_Observer_Iterator *et = (void *)it; 193 Efl_Observer_Iterator *et = (void *)it;
172 194
173 eina_iterator_free(et->classes);
174 EINA_MAGIC_SET(&et->iterator, 0); 195 EINA_MAGIC_SET(&et->iterator, 0);
175 free(et); 196 free(et);
176} 197}
@@ -190,7 +211,8 @@ _efl_observable_observers_iterator_new(Eo *obj EINA_UNUSED, Efl_Observable_Data
190 if (!it) return NULL; 211 if (!it) return NULL;
191 212
192 EINA_MAGIC_SET(&it->iterator, EINA_MAGIC_ITERATOR); 213 EINA_MAGIC_SET(&it->iterator, EINA_MAGIC_ITERATOR);
193 it->classes = eina_list_iterator_new(observers->list); 214 it->current = observers->list;
215 it->next = eina_list_next(observers->list);
194 216
195 it->iterator.version = EINA_ITERATOR_VERSION; 217 it->iterator.version = EINA_ITERATOR_VERSION;
196 it->iterator.next = _efl_observable_observers_iterator_next; 218 it->iterator.next = _efl_observable_observers_iterator_next;
@@ -212,9 +234,7 @@ _efl_observable_observers_update(Eo *obj, Efl_Observable_Data *pd, const char *k
212 if (!it) return; 234 if (!it) return;
213 235
214 EINA_ITERATOR_FOREACH(it, o) 236 EINA_ITERATOR_FOREACH(it, o)
215 { 237 efl_observer_update(o, obj, key, data);
216 efl_observer_update(o, obj, key, data);
217 }
218} 238}
219 239
220typedef struct 240typedef struct
@@ -266,6 +286,14 @@ _efl_observable_iterator_tuple_free(Eina_Iterator *it)
266 eina_iterator_free(tuple->data); 286 eina_iterator_free(tuple->data);
267 free(tuple); 287 free(tuple);
268 } 288 }
289
290 Efl_Observable_Data *pd = efl_data_scope_get(et->obs, EFL_OBSERVABLE_CLASS);
291 if (pd)
292 {
293 pd->walking--;
294 _process_deletion(et->obs, pd);
295 }
296
269 EINA_MAGIC_SET(&et->iterator, 0); 297 EINA_MAGIC_SET(&et->iterator, 0);
270 free(et); 298 free(et);
271} 299}
@@ -283,6 +311,7 @@ _efl_observable_iterator_tuple_new(Eo *obj, Efl_Observable_Data *pd)
283 EINA_MAGIC_SET(&it->iterator, EINA_MAGIC_ITERATOR); 311 EINA_MAGIC_SET(&it->iterator, EINA_MAGIC_ITERATOR);
284 it->classes = eina_hash_iterator_key_new(pd->observers); 312 it->classes = eina_hash_iterator_key_new(pd->observers);
285 it->obs = obj; 313 it->obs = obj;
314 pd->walking++;
286 315
287 it->iterator.version = EINA_ITERATOR_VERSION; 316 it->iterator.version = EINA_ITERATOR_VERSION;
288 it->iterator.next = _efl_observable_iterator_tuple_next; 317 it->iterator.next = _efl_observable_iterator_tuple_next;