summaryrefslogtreecommitdiff
path: root/src/lib/eo
diff options
context:
space:
mode:
authorJean-Philippe Andre <jp.andre@samsung.com>2017-04-18 19:57:53 +0900
committerJean-Philippe Andre <jp.andre@samsung.com>2017-04-19 11:04:12 +0900
commit85636658e00de58db1a3c5f8b03e495a5ad1bda8 (patch)
tree038bb414e0de4f636f7bc307fb7040962cd9a620 /src/lib/eo
parentc9469e0b011c1e4ee2f5e86e5df2a334820b6c6a (diff)
eo: Remove lock from efl_super
I've always really disliked this lock. If someone calls a non-eo function by accident with efl_super() then you'll most likely end up in a deadlock. This adds the cur_klass pointer to the object itself, exploiting the fact that we have 8 bytes of padding (on 64 bits, at least). Also, this opens the door to efl_cast() which would be similar to efl_super() except that only a dynamic cast is done, not a call to the parent function. make benchmark shows a performance improvement, surprisingly. This is a bit experimental. See also the following commit (efl_cast)
Diffstat (limited to 'src/lib/eo')
-rw-r--r--src/lib/eo/eo.c58
-rw-r--r--src/lib/eo/eo_private.h2
2 files changed, 31 insertions, 29 deletions
diff --git a/src/lib/eo/eo.c b/src/lib/eo/eo.c
index ae06df74f0..5410696994 100644
--- a/src/lib/eo/eo.c
+++ b/src/lib/eo/eo.c
@@ -372,35 +372,44 @@ _eo_kls_itr_next(const _Efl_Class *orig_kls, const _Efl_Class *cur_klass, Efl_Ob
372 372
373/************************************ EO ************************************/ 373/************************************ EO ************************************/
374 374
375static const _Efl_Class *_super_class = NULL; 375static EFL_FUNC_TLS _Efl_Class *_super_klass = NULL;
376static Eina_Spinlock _super_class_lock;
377 376
378EAPI Eo * 377EAPI Eo *
379efl_super(const Eo *obj, const Efl_Class *cur_klass) 378efl_super(const Eo *eo_id, const Efl_Class *cur_klass)
380{ 379{
381 EO_CLASS_POINTER_GOTO(cur_klass, klass, err); 380 EO_CLASS_POINTER_GOTO(cur_klass, super_klass, err);
382 381
383#ifdef EO_DEBUG 382#ifdef EO_DEBUG
384 if (EINA_UNLIKELY(!_eo_is_a_obj(obj) && !_eo_is_a_class(obj))) goto err_obj; 383 if (EINA_UNLIKELY(!_eo_is_a_obj(eo_id) && !_eo_is_a_class(eo_id))) goto err_obj;
385 if (EINA_UNLIKELY(!efl_isa(obj, cur_klass))) goto err_obj_hierarchy; 384 if (EINA_UNLIKELY(!efl_isa(eo_id, cur_klass))) goto err_obj_hierarchy;
386#endif 385#endif
387 386
388 /* FIXME: Switch to atomic operations intead of lock. */ 387 if (EINA_UNLIKELY(!_eo_is_a_obj(eo_id)))
389 eina_spinlock_take(&_super_class_lock); 388 goto do_klass;
390 _super_class = klass; 389
390 EO_OBJ_POINTER_RETURN_VAL(eo_id, obj, NULL);
391 obj->cur_klass = super_klass;
392 obj->super = EINA_TRUE;
393 EO_OBJ_DONE(eo_id);
394
395 return (Eo *) eo_id;
396
397do_klass:
398 // efl_super(Class) is extremely rarely used, so TLS write is fine
399 _super_klass = super_klass;
400 return (Eo *) eo_id;
391 401
392 return (Eo *) ((Eo_Id) obj | MASK_SUPER_TAG);
393err: 402err:
394 _EO_POINTER_ERR(cur_klass, "Class (%p) is an invalid ref.", cur_klass); 403 _EO_POINTER_ERR(cur_klass, "Class (%p) is an invalid ref.", cur_klass);
395 return NULL; 404 return NULL;
396#ifdef EO_DEBUG 405#ifdef EO_DEBUG
397err_obj: 406err_obj:
398 _EO_POINTER_ERR(obj, "Object (%p) is an invalid ref, class=%p (%s).", obj, cur_klass, efl_class_name_get(cur_klass)); 407 _EO_POINTER_ERR(eo_id, "Object (%p) is an invalid ref, class=%p (%s).", eo_id, cur_klass, efl_class_name_get(cur_klass));
399 return NULL; 408 return NULL;
400err_obj_hierarchy: 409err_obj_hierarchy:
401 _EO_POINTER_ERR(obj, "Object (%p) class=%p (%s) is not an instance of class=%p (%s).", obj, efl_class_get(obj), efl_class_name_get(obj), cur_klass, efl_class_name_get(cur_klass)); 410 _EO_POINTER_ERR(eo_id, "Object (%p) class=%p (%s) is not an instance of class=%p (%s).", eo_id, efl_class_get(eo_id), efl_class_name_get(eo_id), cur_klass, efl_class_name_get(cur_klass));
402#endif
403 return NULL; 411 return NULL;
412#endif
404} 413}
405 414
406EAPI Eina_Bool 415EAPI Eina_Bool
@@ -414,15 +423,6 @@ _efl_object_call_resolve(Eo *eo_id, const char *func_name, Efl_Object_Op_Call_Da
414 Eina_Bool is_obj; 423 Eina_Bool is_obj;
415 Eina_Bool is_override = EINA_FALSE; 424 Eina_Bool is_override = EINA_FALSE;
416 425
417 if (((Eo_Id) eo_id) & MASK_SUPER_TAG)
418 {
419 cur_klass = _super_class;
420 _super_class = NULL;
421 eina_spinlock_release(&_super_class_lock);
422
423 eo_id = (Eo *) ((Eo_Id) eo_id & ~MASK_SUPER_TAG);
424 }
425
426 if (EINA_UNLIKELY(!eo_id)) return EINA_FALSE; 426 if (EINA_UNLIKELY(!eo_id)) return EINA_FALSE;
427 427
428 call->eo_id = eo_id; 428 call->eo_id = eo_id;
@@ -436,6 +436,11 @@ _efl_object_call_resolve(Eo *eo_id, const char *func_name, Efl_Object_Op_Call_Da
436 obj = _obj; 436 obj = _obj;
437 klass = _obj->klass; 437 klass = _obj->klass;
438 vtable = EO_VTABLE(obj); 438 vtable = EO_VTABLE(obj);
439 if (_obj->cur_klass)
440 {
441 cur_klass = _obj->cur_klass;
442 _obj->cur_klass = NULL;
443 }
439 444
440 if (_obj_is_override(obj) && cur_klass && 445 if (_obj_is_override(obj) && cur_klass &&
441 (_eo_class_id_get(cur_klass) == EFL_OBJECT_OVERRIDE_CLASS)) 446 (_eo_class_id_get(cur_klass) == EFL_OBJECT_OVERRIDE_CLASS))
@@ -608,6 +613,8 @@ ok_klass:
608 EO_CLASS_POINTER_GOTO_PROXY(eo_id, _klass, err_klass); 613 EO_CLASS_POINTER_GOTO_PROXY(eo_id, _klass, err_klass);
609 klass = _klass; 614 klass = _klass;
610 vtable = &klass->vtable; 615 vtable = &klass->vtable;
616 cur_klass = _super_klass;
617 if (cur_klass) _super_klass = NULL;
611 call->obj = NULL; 618 call->obj = NULL;
612 call->data = NULL; 619 call->data = NULL;
613 } 620 }
@@ -2101,12 +2108,6 @@ efl_object_init(void)
2101 return EINA_FALSE; 2108 return EINA_FALSE;
2102 } 2109 }
2103 2110
2104 if (!eina_spinlock_new(&_super_class_lock))
2105 {
2106 ERR("Could not init lock.");
2107 return EINA_FALSE;
2108 }
2109
2110 _eo_log_obj_init(); 2111 _eo_log_obj_init();
2111 2112
2112 eina_magic_string_static_set(EO_EINA_MAGIC, EO_EINA_MAGIC_STR); 2113 eina_magic_string_static_set(EO_EINA_MAGIC, EO_EINA_MAGIC_STR);
@@ -2198,7 +2199,6 @@ efl_object_shutdown(void)
2198 2199
2199 eina_hash_free(_ops_storage); 2200 eina_hash_free(_ops_storage);
2200 2201
2201 eina_spinlock_free(&_super_class_lock);
2202 eina_spinlock_free(&_ops_storage_lock); 2202 eina_spinlock_free(&_ops_storage_lock);
2203 eina_lock_free(&_efl_class_creation_lock); 2203 eina_lock_free(&_efl_class_creation_lock);
2204 2204
diff --git a/src/lib/eo/eo_private.h b/src/lib/eo/eo_private.h
index e115451caa..96cd593854 100644
--- a/src/lib/eo/eo_private.h
+++ b/src/lib/eo/eo_private.h
@@ -107,6 +107,7 @@ struct _Eo_Object
107#endif 107#endif
108 108
109 const Efl_Object_Optional *opt; // eina cow 109 const Efl_Object_Optional *opt; // eina cow
110 _Efl_Class *cur_klass;
110 111
111 short refcount; 112 short refcount;
112 short user_refcount; 113 short user_refcount;
@@ -116,6 +117,7 @@ struct _Eo_Object
116 117
117 Eina_Bool condtor_done:1; 118 Eina_Bool condtor_done:1;
118 Eina_Bool finalized:1; 119 Eina_Bool finalized:1;
120 Eina_Bool super:1;
119 121
120 Eina_Bool del_triggered:1; 122 Eina_Bool del_triggered:1;
121 Eina_Bool destructed:1; 123 Eina_Bool destructed:1;