summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCarsten Haitzler (Rasterman) <raster@rasterman.com>2016-04-13 01:04:11 +0900
committerCarsten Haitzler (Rasterman) <raster@rasterman.com>2016-04-13 01:06:40 +0900
commit8be56c94983c3d2772bb332c0e5c878b4b7d785c (patch)
tree3878f2fca83140d3ec92133ee480ec5934adc380
parent5065356ae69b8d9db79fcffb1eab1b183bf69399 (diff)
eo - add object sotrage in generic values with ref/unref
this adds eo_key_obj_set/get/del() like with data but for object handles so the obj is ref'd as long as the key and parent obj exists and then unreffed on deletion. it also tracks deletion of reffed objects like weak refs and then removes the key automatically. @feature
-rw-r--r--src/lib/eo/eo_base.eo29
-rw-r--r--src/lib/eo/eo_base_class.c225
-rw-r--r--src/tests/eo/suite/eo_test_general.c33
3 files changed, 248 insertions, 39 deletions
diff --git a/src/lib/eo/eo_base.eo b/src/lib/eo/eo_base.eo
index 4e93495f6c..ad6cd68bee 100644
--- a/src/lib/eo/eo_base.eo
+++ b/src/lib/eo/eo_base.eo
@@ -154,6 +154,35 @@ abstract Eo.Base ()
154 @in key: const(char)*; [[the key associated with the data]] 154 @in key: const(char)*; [[the key associated with the data]]
155 } 155 }
156 } 156 }
157 key_obj_set {
158 [[Set generic object reference to object.
159
160 The object will be automatically ref'd when set and unref'd
161 when replaced or deleted or referring object is deleted. If
162 the referenced object is deleted then the key is deleted
163 automatically.
164
165 This is the same key store used by key_data_set etc. so keys
166 are shared and can store only one thing
167 ]]
168 params {
169 @in key: const(char)*; [[the key associated with the object ref]]
170 @in objdata: Eo *; [[the object to set]]
171 }
172 }
173 key_obj_get @const {
174 [[Get generic object reference from object.]]
175 params {
176 @in key: const(char)*; [[the key associated with the object ref]]
177 }
178 return: Eo *; [[the object reference for the key]]
179 }
180 key_obj_del {
181 [[Del generic objecrt reference from object.]]
182 params {
183 @in key: const(char)*; [[the key associated with the object ref]]
184 }
185 }
157 event_thaw { 186 event_thaw {
158 [[thaw events of object. 187 [[thaw events of object.
159 188
diff --git a/src/lib/eo/eo_base_class.c b/src/lib/eo/eo_base_class.c
index 776e92a542..bd402e7b24 100644
--- a/src/lib/eo/eo_base_class.c
+++ b/src/lib/eo/eo_base_class.c
@@ -33,7 +33,8 @@ typedef struct
33{ 33{
34 EINA_INLIST; 34 EINA_INLIST;
35 Eina_Stringshare *key; 35 Eina_Stringshare *key;
36 void *data; 36 void *data;
37 Eina_Bool data_is_obj : 1;
37} Eo_Generic_Data_Node; 38} Eo_Generic_Data_Node;
38 39
39static void 40static void
@@ -43,60 +44,225 @@ _eo_generic_data_node_free(Eo_Generic_Data_Node *node)
43 free(node); 44 free(node);
44} 45}
45 46
47static Eina_Bool
48_eo_base_cb_key_obj_del(void *data, const Eo_Event *event)
49{
50 Eo *parent_obj = data;
51 Eo_Base_Data *pd = eo_data_scope_get(parent_obj, EO_BASE_CLASS);
52
53 if (pd)
54 {
55 Eo_Generic_Data_Node *node;
56
57 EINA_INLIST_FOREACH(pd->generic_data, node)
58 {
59 if ((node->data_is_obj) && (node->data == event->obj))
60 {
61 pd->generic_data = eina_inlist_remove(pd->generic_data,
62 EINA_INLIST_GET(node));
63 eo_event_callback_del(node->data, EO_BASE_EVENT_DEL,
64 _eo_base_cb_key_obj_del, data);
65 eo_unref(node->data);
66 _eo_generic_data_node_free(node);
67 break;
68 }
69 }
70 }
71 return EINA_TRUE;
72}
73
46static void 74static void
47_eo_generic_data_del_all(Eo_Base_Data *pd) 75_eo_generic_data_del_all(Eo *obj, Eo_Base_Data *pd)
48{ 76{
49 Eina_Inlist *nnode; 77 Eo_Generic_Data_Node *node;
50 Eo_Generic_Data_Node *node = NULL;
51 78
52 EINA_INLIST_FOREACH_SAFE(pd->generic_data, nnode, node) 79 while (pd->generic_data)
53 { 80 {
81 node = (Eo_Generic_Data_Node *)pd->generic_data;
54 pd->generic_data = eina_inlist_remove(pd->generic_data, 82 pd->generic_data = eina_inlist_remove(pd->generic_data,
55 EINA_INLIST_GET(node)); 83 EINA_INLIST_GET(node));
56 84 if (node->data_is_obj)
85 {
86 eo_event_callback_del(node->data, EO_BASE_EVENT_DEL,
87 _eo_base_cb_key_obj_del, obj);
88 eo_unref(node->data);
89 }
57 _eo_generic_data_node_free(node); 90 _eo_generic_data_node_free(node);
58 } 91 }
59} 92}
60 93
61EOLIAN static void 94EOLIAN static void
62_eo_base_key_data_set(Eo *obj, Eo_Base_Data *pd, 95_eo_base_key_data_set(Eo *obj, Eo_Base_Data *pd, const char *key, const void *data)
63 const char *key, const void *data)
64{ 96{
65 Eo_Generic_Data_Node *node; 97 Eo_Generic_Data_Node *node;
66 98
67 if (!key) return; 99 if (!key) return;
100 EINA_INLIST_FOREACH(pd->generic_data, node)
101 {
102 if (!strcmp(node->key, key))
103 {
104 if ((!node->data_is_obj) && (node->data == data)) return;
105 pd->generic_data = eina_inlist_remove(pd->generic_data,
106 EINA_INLIST_GET(node));
107 if (node->data_is_obj)
108 {
109 eo_event_callback_del(node->data, EO_BASE_EVENT_DEL,
110 _eo_base_cb_key_obj_del, obj);
111 eo_unref(node->data);
112 }
113 _eo_generic_data_node_free(node);
114 break;
115 }
116 }
68 117
69 eo_key_data_del(obj, key); 118 node = calloc(1, sizeof(Eo_Generic_Data_Node));
70
71 node = malloc(sizeof(Eo_Generic_Data_Node));
72 if (!node) return; 119 if (!node) return;
73 node->key = eina_stringshare_add(key); 120 node->key = eina_stringshare_add(key);
74 node->data = (void *) data; 121 node->data = (void *)data;
122 node->data_is_obj = EINA_FALSE;
75 pd->generic_data = eina_inlist_prepend(pd->generic_data, 123 pd->generic_data = eina_inlist_prepend(pd->generic_data,
76 EINA_INLIST_GET(node)); 124 EINA_INLIST_GET(node));
77} 125}
78 126
79EOLIAN static void * 127EOLIAN static void *
80_eo_base_key_data_get(const Eo *obj EINA_UNUSED, Eo_Base_Data *pd, const char *key) 128_eo_base_key_data_get(const Eo *obj, Eo_Base_Data *pd, const char *key)
81{ 129{
82 /* We don't really change it... */
83 Eo_Generic_Data_Node *node; 130 Eo_Generic_Data_Node *node;
131
84 if (!key) return NULL; 132 if (!key) return NULL;
133 EINA_INLIST_FOREACH(pd->generic_data, node)
134 {
135 if (!strcmp(node->key, key))
136 {
137 if (!node->data_is_obj)
138 {
139 pd->generic_data = eina_inlist_promote(pd->generic_data,
140 EINA_INLIST_GET(node));
141 return node->data;
142 }
143 else
144 {
145 ERR("Object %p key '%s' is an object, not raw data",
146 obj, key);
147 return NULL;
148 }
149 }
150 }
151 return NULL;
152}
153
154EOLIAN static void
155_eo_base_key_data_del(Eo *obj, Eo_Base_Data *pd, const char *key)
156{
157 Eo_Generic_Data_Node *node;
158
159 if (!key) return;
160 EINA_INLIST_FOREACH(pd->generic_data, node)
161 {
162 if (!strcmp(node->key, key))
163 {
164 pd->generic_data = eina_inlist_remove(pd->generic_data,
165 EINA_INLIST_GET(node));
166 if (node->data_is_obj)
167 {
168 eo_event_callback_del(node->data, EO_BASE_EVENT_DEL,
169 _eo_base_cb_key_obj_del, obj);
170 eo_unref(node->data);
171 }
172 _eo_generic_data_node_free(node);
173 return;
174 }
175 }
176}
177
178EOLIAN static void
179_eo_base_key_obj_set(Eo *obj, Eo_Base_Data *pd, const char *key, Eo *objdata)
180{
181 Eo_Generic_Data_Node *node;
85 182
183 if (!key) return;
86 EINA_INLIST_FOREACH(pd->generic_data, node) 184 EINA_INLIST_FOREACH(pd->generic_data, node)
87 { 185 {
88 if (!strcmp(node->key, key)) 186 if (!strcmp(node->key, key))
89 { 187 {
90 pd->generic_data = 188 if ((node->data_is_obj) && (node->data == objdata)) return;
91 eina_inlist_promote(pd->generic_data, EINA_INLIST_GET(node)); 189 pd->generic_data = eina_inlist_remove(pd->generic_data,
92 return node->data; 190 EINA_INLIST_GET(node));
191 if (node->data_is_obj)
192 {
193 eo_event_callback_del(node->data, EO_BASE_EVENT_DEL,
194 _eo_base_cb_key_obj_del, obj);
195 eo_unref(node->data);
196 }
197 _eo_generic_data_node_free(node);
198 break;
93 } 199 }
94 } 200 }
95 201
202 node = calloc(1, sizeof(Eo_Generic_Data_Node));
203 if (!node) return;
204 node->key = eina_stringshare_add(key);
205 node->data = (void *)objdata;
206 node->data_is_obj = EINA_TRUE;
207 eo_event_callback_add(node->data, EO_BASE_EVENT_DEL,
208 _eo_base_cb_key_obj_del, obj);
209 eo_ref(node->data);
210 pd->generic_data = eina_inlist_prepend(pd->generic_data,
211 EINA_INLIST_GET(node));
212}
213
214EOLIAN static Eo *
215_eo_base_key_obj_get(const Eo *obj, Eo_Base_Data *pd, const char *key)
216{
217 Eo_Generic_Data_Node *node;
218
219 if (!key) return NULL;
220 EINA_INLIST_FOREACH(pd->generic_data, node)
221 {
222 if (!strcmp(node->key, key))
223 {
224 if (node->data_is_obj)
225 {
226 pd->generic_data = eina_inlist_promote(pd->generic_data,
227 EINA_INLIST_GET(node));
228 return node->data;
229 }
230 else
231 {
232 ERR("Object %p key '%s' is an object, not an object",
233 obj, key);
234 return NULL;
235 }
236 }
237 }
96 return NULL; 238 return NULL;
97} 239}
98 240
99EOLIAN static void 241EOLIAN static void
242_eo_base_key_obj_del(Eo *obj EINA_UNUSED, Eo_Base_Data *pd, const char *key)
243{
244 Eo_Generic_Data_Node *node;
245
246 if (!key) return;
247 EINA_INLIST_FOREACH(pd->generic_data, node)
248 {
249 if (!strcmp(node->key, key))
250 {
251 pd->generic_data = eina_inlist_remove(pd->generic_data,
252 EINA_INLIST_GET(node));
253 if (node->data_is_obj)
254 {
255 eo_event_callback_del(node->data, EO_BASE_EVENT_DEL,
256 _eo_base_cb_key_obj_del, obj);
257 eo_unref(node->data);
258 }
259 _eo_generic_data_node_free(node);
260 return;
261 }
262 }
263}
264
265EOLIAN static void
100_eo_base_parent_set(Eo *obj, Eo_Base_Data *pd, Eo *parent_id) 266_eo_base_parent_set(Eo *obj, Eo_Base_Data *pd, Eo *parent_id)
101{ 267{
102 if (pd->parent == parent_id) 268 if (pd->parent == parent_id)
@@ -265,25 +431,6 @@ _eo_base_dbg_info_get(Eo *obj EINA_UNUSED, Eo_Base_Data *pd EINA_UNUSED, Eo_Dbg_
265 return; 431 return;
266} 432}
267 433
268EOLIAN static void
269_eo_base_key_data_del(Eo *obj EINA_UNUSED, Eo_Base_Data *pd, const char *key)
270{
271 Eo_Generic_Data_Node *node;
272
273 if (!key) return;
274
275 EINA_INLIST_FOREACH(pd->generic_data, node)
276 {
277 if (!strcmp(node->key, key))
278 {
279 pd->generic_data = eina_inlist_remove(pd->generic_data,
280 EINA_INLIST_GET(node));
281 _eo_generic_data_node_free(node);
282 return;
283 }
284 }
285}
286
287/* Weak reference. */ 434/* Weak reference. */
288 435
289static inline size_t 436static inline size_t
@@ -996,7 +1143,7 @@ _eo_base_destructor(Eo *obj, Eo_Base_Data *pd)
996 eo_parent_set(obj, NULL); 1143 eo_parent_set(obj, NULL);
997 } 1144 }
998 1145
999 _eo_generic_data_del_all(pd); 1146 _eo_generic_data_del_all(obj, pd);
1000 _wref_destruct(pd); 1147 _wref_destruct(pd);
1001 _eo_callback_remove_all(pd); 1148 _eo_callback_remove_all(pd);
1002 1149
diff --git a/src/tests/eo/suite/eo_test_general.c b/src/tests/eo/suite/eo_test_general.c
index fcaa115e99..9f689f3082 100644
--- a/src/tests/eo/suite/eo_test_general.c
+++ b/src/tests/eo/suite/eo_test_general.c
@@ -598,6 +598,9 @@ START_TEST(eo_generic_data)
598{ 598{
599 eo_init(); 599 eo_init();
600 Eo *obj = eo_add(SIMPLE_CLASS, NULL); 600 Eo *obj = eo_add(SIMPLE_CLASS, NULL);
601 Eo *obj2 = eo_add(SIMPLE_CLASS, NULL);
602 Eo *obj3 = eo_add(SIMPLE_CLASS, NULL);
603 Eo *objtmp;
601 void *data = NULL; 604 void *data = NULL;
602 605
603 eo_key_data_set(obj, "test1", (void *) 1); 606 eo_key_data_set(obj, "test1", (void *) 1);
@@ -626,7 +629,37 @@ START_TEST(eo_generic_data)
626 data = eo_key_data_get(obj, "test1"); 629 data = eo_key_data_get(obj, "test1");
627 fail_if(data); 630 fail_if(data);
628 631
632
633
634 eo_key_obj_set(obj, "test1", obj2);
635 objtmp = eo_key_obj_get(obj, "test1");
636 fail_if(obj2 != objtmp);
637 eo_key_obj_del(obj, "test1");
638 objtmp = eo_key_obj_get(obj, "test1");
639 fail_if(objtmp);
640
641 eo_key_obj_set(obj, "test1", obj2);
642 eo_key_obj_set(obj, "test2", obj3);
643 objtmp = eo_key_obj_get(obj, "test1");
644 fail_if(obj2 != objtmp);
645 objtmp = eo_key_obj_get(obj, "test2");
646 fail_if(obj3 != objtmp);
647
648 data = eo_key_obj_get(obj, "test2");
649 fail_if(obj3 != objtmp);
650 eo_key_obj_del(obj, "test2");
651 objtmp = eo_key_obj_get(obj, "test2");
652 fail_if(objtmp);
653
654 objtmp = eo_key_obj_get(obj, "test1");
655 fail_if(obj2 != objtmp);
656 eo_key_obj_del(obj, "test1");
657 objtmp = eo_key_obj_get(obj, "test1");
658 fail_if(objtmp);
659
629 eo_unref(obj); 660 eo_unref(obj);
661 eo_unref(obj2);
662 eo_unref(obj3);
630 663
631 eo_shutdown(); 664 eo_shutdown();
632} 665}