2012-09-04 00:03:02 -07:00
# ifdef HAVE_CONFIG_H
# include <config.h>
# endif
2015-12-28 05:22:29 -08:00
# if defined HAVE_DLADDR && ! defined _WIN32
2014-05-07 15:15:30 -07:00
# include <dlfcn.h>
# endif
2012-04-05 08:31:15 -07:00
# include <Eina.h>
2012-05-01 00:40:14 -07:00
# include "Eo.h"
2013-04-18 04:19:02 -07:00
# include "eo_ptr_indirection.h"
2012-05-01 00:40:14 -07:00
# include "eo_private.h"
2016-03-29 06:47:22 -07:00
# include "eo_add_fallback.h"
2012-04-05 08:31:15 -07:00
2016-08-09 06:10:05 -07:00
# include "efl_object_override.eo.c"
2016-05-19 03:33:17 -07:00
2012-08-20 00:56:17 -07:00
# define EO_CLASS_IDS_FIRST 1
2016-08-15 06:44:41 -07:00
# define EFL_OBJECT_OP_IDS_FIRST 1
2012-04-16 05:36:42 -07:00
2016-08-15 06:44:41 -07:00
/* Used inside the class_get functions of classes, see #EFL_DEFINE_CLASS */
EAPI Eina_Spinlock _efl_class_creation_lock ;
EAPI unsigned int _efl_object_init_generation = 1 ;
2012-05-01 00:40:14 -07:00
int _eo_log_dom = - 1 ;
2012-04-05 08:31:15 -07:00
2016-08-09 06:10:05 -07:00
static _Efl_Class * * _eo_classes = NULL ;
2016-04-23 20:00:37 -07:00
static Eo_Id _eo_classes_last_id = 0 ;
static Eo_Id _eo_classes_alloc = 0 ;
2016-08-15 06:44:41 -07:00
static int _efl_object_init_count = 0 ;
static Efl_Object_Op _eo_ops_last_id = 0 ;
2015-09-28 09:18:43 -07:00
static Eina_Hash * _ops_storage = NULL ;
static Eina_Spinlock _ops_storage_lock ;
2012-04-05 08:31:15 -07:00
2013-04-10 19:58:53 -07:00
static size_t _eo_sz = 0 ;
2013-06-17 14:33:19 -07:00
static size_t _eo_class_sz = 0 ;
2013-04-10 19:58:53 -07:00
2013-09-26 14:31:39 -07:00
static void _eo_condtor_reset ( _Eo_Object * obj ) ;
2016-08-15 06:44:41 -07:00
static inline void * _efl_data_scope_get ( const _Eo_Object * obj , const _Efl_Class * klass ) ;
static inline void * _efl_data_xref_internal ( const char * file , int line , _Eo_Object * obj , const _Efl_Class * klass , const _Eo_Object * ref_obj ) ;
static inline void _efl_data_xunref_internal ( _Eo_Object * obj , void * data , const _Eo_Object * ref_obj ) ;
2012-04-05 08:31:15 -07:00
/* Start of Dich */
2014-03-11 08:50:44 -07:00
/* We are substracting the mask here instead of "AND"ing because it's a hot path,
* it should be a valid class at this point , and this lets the compiler do 1
* substraction at compile time . */
# define _UNMASK_ID(id) ((id) - MASK_CLASS_TAG)
2012-05-06 05:03:23 -07:00
# define ID_CLASS_GET(id) ({ \
2016-08-09 06:10:05 -07:00
( _Efl_Class * ) ( ( ( _UNMASK_ID ( id ) < = _eo_classes_last_id ) & & ( _UNMASK_ID ( id ) > 0 ) ) ? \
2014-03-11 08:50:44 -07:00
( _eo_classes [ _UNMASK_ID ( id ) - 1 ] ) : NULL ) ; \
2012-05-06 05:03:23 -07:00
} )
2016-08-15 09:11:13 -07:00
static inline void
_vtable_chain2_unref ( Dich_Chain2 * chain )
{
if ( - - ( chain - > refcount ) = = 0 )
{
free ( chain ) ;
}
}
2012-05-07 23:56:57 -07:00
static inline void
2016-05-18 10:12:39 -07:00
_vtable_chain_alloc ( Dich_Chain1 * chain1 )
2012-05-07 23:56:57 -07:00
{
2016-08-15 09:11:13 -07:00
chain1 - > chain2 = calloc ( 1 , sizeof ( * ( chain1 - > chain2 ) ) ) ;
chain1 - > chain2 - > refcount = 1 ;
}
static inline void _vtable_chain_write_prepare ( Dich_Chain1 * dst ) ;
static inline void
_vtable_chain_merge ( Dich_Chain1 * dst , const Dich_Chain1 * src )
{
Eina_Bool writeable = EINA_FALSE ;
size_t j ;
const op_type_funcs * sf = src - > chain2 - > funcs ;
op_type_funcs * df = dst - > chain2 - > funcs ;
if ( df = = sf )
2012-05-07 23:56:57 -07:00
{
2016-08-15 09:11:13 -07:00
/* Skip if the chain is the same. */
return ;
}
for ( j = 0 ; j < DICH_CHAIN_LAST_SIZE ; j + + , df + + , sf + + )
{
if ( sf - > func & & memcmp ( df , sf , sizeof ( * df ) ) )
{
if ( ! writeable )
{
_vtable_chain_write_prepare ( dst ) ;
df = dst - > chain2 - > funcs + j ;
}
memcpy ( df , sf , sizeof ( * df ) ) ;
}
}
}
static inline void
_vtable_chain_write_prepare ( Dich_Chain1 * dst )
{
if ( ! dst - > chain2 )
{
_vtable_chain_alloc ( dst ) ;
return ;
}
else if ( dst - > chain2 - > refcount = = 1 )
{
/* We own it, no need to duplicate */
return ;
}
Dich_Chain1 old ;
old . chain2 = dst - > chain2 ;
_vtable_chain_alloc ( dst ) ;
_vtable_chain_merge ( dst , & old ) ;
_vtable_chain2_unref ( old . chain2 ) ;
}
static inline void
_vtable_chain_copy_ref ( Dich_Chain1 * dst , const Dich_Chain1 * src )
{
if ( dst - > chain2 )
{
_vtable_chain_merge ( dst , src ) ;
}
else
{
dst - > chain2 = src - > chain2 ;
dst - > chain2 - > refcount + + ;
2012-05-07 23:56:57 -07:00
}
}
static inline void
2016-05-18 10:12:39 -07:00
_vtable_copy_all ( Eo_Vtable * dst , const Eo_Vtable * src )
2012-05-07 23:56:57 -07:00
{
2016-08-15 06:44:41 -07:00
Efl_Object_Op i ;
2012-05-07 23:56:57 -07:00
const Dich_Chain1 * sc1 = src - > chain ;
Dich_Chain1 * dc1 = dst - > chain ;
2016-05-18 10:12:39 -07:00
for ( i = 0 ; i < src - > size ; i + + , sc1 + + , dc1 + + )
2012-05-07 23:56:57 -07:00
{
2016-08-15 09:11:13 -07:00
if ( sc1 - > chain2 )
2012-05-07 23:56:57 -07:00
{
2016-08-15 09:11:13 -07:00
_vtable_chain_copy_ref ( dc1 , sc1 ) ;
2012-05-07 23:56:57 -07:00
}
}
}
static inline const op_type_funcs *
2016-08-15 06:44:41 -07:00
_vtable_func_get ( const Eo_Vtable * vtable , Efl_Object_Op op )
2012-04-05 08:31:15 -07:00
{
2012-07-10 07:01:45 -07:00
size_t idx1 = DICH_CHAIN1 ( op ) ;
2016-05-18 10:12:39 -07:00
if ( EINA_UNLIKELY ( idx1 > = vtable - > size ) )
2012-04-05 08:31:15 -07:00
return NULL ;
2016-05-18 10:12:39 -07:00
Dich_Chain1 * chain1 = & vtable - > chain [ idx1 ] ;
2016-08-15 09:11:13 -07:00
if ( EINA_UNLIKELY ( ! chain1 - > chain2 ) )
2012-07-10 07:01:45 -07:00
return NULL ;
2016-08-15 09:11:13 -07:00
return & chain1 - > chain2 - > funcs [ DICH_CHAIN_LAST ( op ) ] ;
2012-04-05 08:31:15 -07:00
}
2015-10-16 02:08:33 -07:00
/* XXX: Only used for a debug message below. Doesn't matter that it's slow. */
2016-08-09 06:10:05 -07:00
static const _Efl_Class *
2016-08-15 06:44:41 -07:00
_eo_op_class_get ( Efl_Object_Op op )
2015-10-16 02:08:33 -07:00
{
2016-08-09 06:10:05 -07:00
_Efl_Class * * itr = _eo_classes ;
2015-10-16 02:08:33 -07:00
int mid , max , min ;
min = 0 ;
max = _eo_classes_last_id - 1 ;
while ( min < = max )
{
mid = ( min + max ) / 2 ;
if ( itr [ mid ] - > base_id + itr [ mid ] - > desc - > ops . count < op )
min = mid + 1 ;
else if ( itr [ mid ] - > base_id > op )
max = mid - 1 ;
else
return itr [ mid ] ;
}
return NULL ;
}
2014-01-09 05:43:26 -08:00
static inline Eina_Bool
2016-08-16 08:28:33 -07:00
_vtable_func_set ( Eo_Vtable * vtable , const _Efl_Class * klass , Efl_Object_Op op , Eo_Op_Func_Type func )
2012-04-05 08:31:15 -07:00
{
2014-01-03 07:02:00 -08:00
op_type_funcs * fsrc ;
2012-07-10 07:01:45 -07:00
size_t idx1 = DICH_CHAIN1 ( op ) ;
2016-05-19 03:33:17 -07:00
Dich_Chain1 * chain1 = & vtable - > chain [ idx1 ] ;
2016-08-15 09:11:13 -07:00
_vtable_chain_write_prepare ( chain1 ) ;
fsrc = & chain1 - > chain2 - > funcs [ DICH_CHAIN_LAST ( op ) ] ;
2014-01-03 07:02:00 -08:00
if ( fsrc - > src = = klass )
2012-07-26 05:21:01 -07:00
{
2016-08-09 06:10:05 -07:00
const _Efl_Class * op_kls = _eo_op_class_get ( op ) ;
2016-05-19 03:27:41 -07:00
ERR ( " Class '%s': Overriding already set func %p for op %d (%s) with %p. " ,
2015-09-28 09:18:43 -07:00
klass - > desc - > name , fsrc - > func , op , op_kls - > desc - > name , func ) ;
2014-01-09 05:43:26 -08:00
return EINA_FALSE ;
2012-07-26 05:21:01 -07:00
}
2014-01-03 07:02:00 -08:00
fsrc - > func = func ;
fsrc - > src = klass ;
2014-01-09 05:43:26 -08:00
return EINA_TRUE ;
2012-04-05 08:31:15 -07:00
}
2016-05-19 03:33:17 -07:00
void
_vtable_func_clean_all ( Eo_Vtable * vtable )
2012-04-05 08:31:15 -07:00
{
2012-05-06 05:03:23 -07:00
size_t i ;
2016-05-19 03:33:17 -07:00
Dich_Chain1 * chain1 = vtable - > chain ;
2012-04-05 08:31:15 -07:00
2016-05-19 03:33:17 -07:00
for ( i = 0 ; i < vtable - > size ; i + + , chain1 + + )
2012-05-06 05:03:23 -07:00
{
2016-08-15 09:11:13 -07:00
if ( chain1 - > chain2 )
_vtable_chain2_unref ( chain1 - > chain2 ) ;
2012-04-05 08:31:15 -07:00
}
2016-05-19 03:33:17 -07:00
free ( vtable - > chain ) ;
vtable - > chain = NULL ;
2012-04-05 08:31:15 -07:00
}
/* END OF DICH */
2013-09-26 14:32:43 -07:00
# ifdef HAVE_EO_ID
2015-10-15 04:56:15 -07:00
# define _EO_ID_GET(Id) ((Eo_Id) (Id))
2013-09-26 14:32:43 -07:00
# else
2015-10-15 04:56:15 -07:00
# define _EO_ID_GET(Id) ((Eo_Id) ((Id) ? ((Eo_Header *) (Id))->id : 0))
2013-09-26 14:32:43 -07:00
# endif
2015-10-15 04:56:15 -07:00
static inline Eina_Bool
_eo_is_a_obj ( const Eo * eo_id )
{
Eo_Id oid = ( Eo_Id ) _EO_ID_GET ( eo_id ) ;
return ! ! ( oid & MASK_OBJ_TAG ) ;
}
static inline Eina_Bool
_eo_is_a_class ( const Eo * eo_id )
{
Eo_Id oid = ( Eo_Id ) _EO_ID_GET ( eo_id ) ;
return ! ! ( oid & MASK_CLASS_TAG ) ;
2013-09-26 14:32:43 -07:00
}
2016-08-09 06:10:05 -07:00
static inline _Efl_Class *
_eo_class_pointer_get ( const Efl_Class * klass_id )
2013-04-18 04:19:02 -07:00
{
# ifdef HAVE_EO_ID
2013-09-27 02:50:06 -07:00
return ID_CLASS_GET ( ( Eo_Id ) klass_id ) ;
2013-04-18 04:19:02 -07:00
# else
2016-08-09 06:10:05 -07:00
return ( _Efl_Class * ) klass_id ;
2013-04-18 04:19:02 -07:00
# endif
}
2015-09-28 06:15:15 -07:00
static const char *
2016-08-09 06:10:05 -07:00
_eo_op_desc_name_get ( const Efl_Op_Description * desc )
2015-09-28 06:15:15 -07:00
{
static const char * fct_name = " unknown " ;
if ( ! desc )
{
return fct_name ;
}
# ifndef _WIN32
# ifdef HAVE_DLADDR
static Dl_info info ;
if ( dladdr ( desc - > api_func , & info ) ! = 0 )
fct_name = info . dli_sname ;
# endif
# else
2015-09-28 07:24:44 -07:00
fct_name = desc - > api_func ; /* Same on windows */
2015-09-28 06:15:15 -07:00
# endif
return fct_name ;
}
2013-11-11 05:06:51 -08:00
static inline const op_type_funcs *
2016-08-15 06:44:41 -07:00
_eo_kls_itr_next ( const _Efl_Class * orig_kls , const _Efl_Class * cur_klass , Efl_Object_Op op )
2012-04-11 00:05:30 -07:00
{
2016-08-09 06:10:05 -07:00
const _Efl_Class * * kls_itr = NULL ;
2012-05-07 23:56:57 -07:00
2012-07-18 05:27:09 -07:00
/* Find the kls itr. */
kls_itr = orig_kls - > mro ;
2013-03-13 09:04:04 -07:00
while ( * kls_itr & & ( * kls_itr ! = cur_klass ) )
2012-07-18 05:27:09 -07:00
kls_itr + + ;
2012-05-07 23:56:57 -07:00
2012-07-18 05:27:09 -07:00
if ( * kls_itr )
2012-04-11 00:05:33 -07:00
{
2012-07-18 05:27:09 -07:00
kls_itr + + ;
2012-07-31 00:15:33 -07:00
while ( * kls_itr )
2012-07-18 05:27:09 -07:00
{
2016-05-18 10:12:39 -07:00
const op_type_funcs * fsrc = _vtable_func_get ( & ( * kls_itr ) - > vtable , op ) ;
2012-07-31 00:34:27 -07:00
if ( ! fsrc | | ! fsrc - > func )
2012-07-31 00:15:33 -07:00
{
kls_itr + + ;
continue ;
}
2013-11-11 05:06:51 -08:00
return fsrc ;
2012-07-18 05:27:09 -07:00
}
2012-04-11 00:05:33 -07:00
}
2012-07-18 05:27:09 -07:00
return NULL ;
2012-04-11 00:05:30 -07:00
}
2014-04-02 01:46:34 -07:00
/************************************ EO ************************************/
2013-07-18 00:10:07 -07:00
2016-08-09 06:10:05 -07:00
static const _Efl_Class * _super_class = NULL ;
2015-11-09 03:45:04 -08:00
static Eina_Spinlock _super_class_lock ;
2013-10-02 05:57:45 -07:00
2015-11-09 03:45:04 -08:00
EAPI Eo *
2016-08-15 06:44:41 -07:00
efl_super ( const Eo * obj , const Efl_Class * cur_klass )
2013-12-25 06:16:34 -08:00
{
2016-05-20 03:47:32 -07:00
EO_CLASS_POINTER_RETURN_VAL ( cur_klass , klass , NULL ) ;
2015-11-09 03:45:04 -08:00
/* FIXME: Switch to atomic operations intead of lock. */
eina_spinlock_take ( & _super_class_lock ) ;
2016-05-20 03:47:32 -07:00
_super_class = klass ;
2014-01-22 02:18:31 -08:00
2015-11-09 03:45:04 -08:00
return ( Eo * ) ( ( Eo_Id ) obj | MASK_SUPER_TAG ) ;
2014-04-22 03:17:26 -07:00
}
2015-11-09 03:45:04 -08:00
EAPI Eina_Bool
2016-08-15 06:44:41 -07:00
_efl_object_call_resolve ( Eo * eo_id , const char * func_name , Efl_Object_Op_Call_Data * call , Efl_Object_Call_Cache * cache , const char * file , int line )
2013-10-02 05:57:45 -07:00
{
2016-08-09 06:10:05 -07:00
const _Efl_Class * klass , * inputklass , * main_klass ;
const _Efl_Class * cur_klass = NULL ;
2015-11-09 03:45:04 -08:00
_Eo_Object * obj = NULL ;
2016-05-19 03:33:17 -07:00
const Eo_Vtable * vtable = NULL ;
2015-11-09 03:45:04 -08:00
const op_type_funcs * func ;
Eina_Bool is_obj ;
2016-05-19 03:33:17 -07:00
Eina_Bool is_override = EINA_FALSE ;
2014-01-22 02:18:31 -08:00
2015-11-09 03:45:04 -08:00
if ( ( ( Eo_Id ) eo_id ) & MASK_SUPER_TAG )
2014-01-22 02:18:31 -08:00
{
2016-05-20 03:47:32 -07:00
cur_klass = _super_class ;
2015-11-09 03:45:04 -08:00
_super_class = NULL ;
eina_spinlock_release ( & _super_class_lock ) ;
2013-10-02 05:57:45 -07:00
2015-11-09 03:45:04 -08:00
eo_id = ( Eo * ) ( ( Eo_Id ) eo_id & ~ MASK_SUPER_TAG ) ;
}
2013-12-30 06:24:15 -08:00
2015-11-09 03:45:04 -08:00
if ( EINA_UNLIKELY ( ! eo_id ) )
return EINA_FALSE ;
2013-12-30 06:24:15 -08:00
2015-11-09 03:45:04 -08:00
call - > eo_id = eo_id ;
2013-12-30 06:24:15 -08:00
2015-11-09 03:45:04 -08:00
is_obj = _eo_is_a_obj ( eo_id ) ;
2013-12-30 08:53:54 -08:00
2015-11-09 03:45:04 -08:00
if ( is_obj )
2013-07-24 15:10:26 -07:00
{
2015-10-12 09:58:44 -07:00
EO_OBJ_POINTER_RETURN_VAL ( eo_id , _obj , EINA_FALSE ) ;
2015-11-09 03:45:04 -08:00
obj = _obj ;
klass = _obj - > klass ;
2016-05-19 03:33:17 -07:00
vtable = obj - > vtable ;
if ( _obj_is_override ( obj ) & & cur_klass & &
2016-08-09 06:10:05 -07:00
( _eo_class_id_get ( cur_klass ) = = EFL_OBJECT_OVERRIDE_CLASS ) )
2016-05-19 03:33:17 -07:00
{
2016-08-15 06:44:41 -07:00
/* Doing a efl_super(obj, EFL_OBJECT_OVERRIDE_CLASS) should result in calling
2016-05-19 03:33:17 -07:00
* as if it ' s a normal class . */
vtable = & klass - > vtable ;
cur_klass = NULL ;
}
is_override = _obj_is_override ( obj ) & & ( cur_klass = = NULL ) ;
2015-11-09 03:45:04 -08:00
call - > obj = obj ;
2016-08-15 06:44:41 -07:00
_efl_ref ( _obj ) ;
2013-07-24 15:10:26 -07:00
}
2015-10-15 04:56:15 -07:00
else
{
EO_CLASS_POINTER_RETURN_VAL ( eo_id , _klass , EINA_FALSE ) ;
2015-11-09 03:45:04 -08:00
klass = _klass ;
2016-05-19 03:33:17 -07:00
vtable = & klass - > vtable ;
2015-11-09 03:45:04 -08:00
call - > obj = NULL ;
call - > data = NULL ;
2014-04-14 02:36:09 -07:00
}
2013-11-11 02:34:35 -08:00
2015-11-09 03:45:04 -08:00
inputklass = main_klass = klass ;
2013-07-30 06:02:35 -07:00
2013-11-11 02:34:35 -08:00
2015-10-23 20:23:53 -07:00
if ( ! cache - > op )
2015-09-28 09:18:43 -07:00
{
ERR ( " %s:%d: unable to resolve %s api func '%s' in class '%s'. " ,
file , line , ( ! is_obj ? " class " : " regular " ) ,
func_name , klass - > desc - > name ) ;
return EINA_FALSE ;
}
2015-10-23 20:23:53 -07:00
/* If we have a current class, we need to itr to the next. */
2015-11-09 03:45:04 -08:00
if ( cur_klass )
2015-10-21 04:06:23 -07:00
{
2015-11-09 03:45:04 -08:00
func = _eo_kls_itr_next ( klass , cur_klass , cache - > op ) ;
2015-10-23 20:23:53 -07:00
if ( ! func )
goto end ;
klass = func - > src ;
}
else
{
2016-08-15 06:44:41 -07:00
# if EFL_OBJECT_CALL_CACHE_SIZE > 0
2016-05-19 03:33:17 -07:00
if ( ! is_override )
{
2016-08-15 06:44:41 -07:00
# if EFL_OBJECT_CALL_CACHE_SIZE > 1
2016-05-19 03:33:17 -07:00
int i ;
2015-10-21 04:06:23 -07:00
2016-08-15 06:44:41 -07:00
for ( i = 0 ; i < EFL_OBJECT_CALL_CACHE_SIZE ; i + + )
2015-10-21 04:06:23 -07:00
# else
2016-05-19 03:33:17 -07:00
const int i = 0 ;
2015-10-21 04:06:23 -07:00
# endif
{
2016-05-19 03:33:17 -07:00
if ( ( const void * ) inputklass = = cache - > index [ i ] . klass )
2015-10-21 04:06:23 -07:00
{
2016-05-19 03:33:17 -07:00
func = ( const op_type_funcs * ) cache - > entry [ i ] . func ;
call - > func = func - > func ;
if ( is_obj )
{
call - > data = ( char * ) obj + cache - > off [ i ] . off ;
}
return EINA_TRUE ;
2015-10-21 04:06:23 -07:00
}
}
}
# endif
2016-05-19 03:33:17 -07:00
func = _vtable_func_get ( vtable , cache - > op ) ;
2014-10-27 15:23:45 -07:00
if ( ! func )
goto end ;
2013-11-11 02:34:35 -08:00
}
2013-07-09 05:21:11 -07:00
2013-11-08 07:30:25 -08:00
if ( EINA_LIKELY ( func - > func & & func - > src ) )
2013-07-08 08:31:36 -07:00
{
2013-07-10 00:24:59 -07:00
call - > func = func - > func ;
2013-12-25 06:16:34 -08:00
2013-11-11 02:34:35 -08:00
if ( is_obj )
2013-12-25 06:16:34 -08:00
{
2016-08-15 06:44:41 -07:00
call - > data = _efl_data_scope_get ( obj , func - > src ) ;
2013-11-07 14:38:36 -08:00
}
2013-12-25 06:16:34 -08:00
2016-08-15 06:44:41 -07:00
# if EFL_OBJECT_CALL_CACHE_SIZE > 0
2016-05-19 03:33:17 -07:00
if ( ! cur_klass & & ! is_override )
2015-10-21 04:06:23 -07:00
{
2016-08-15 06:44:41 -07:00
# if EFL_OBJECT_CALL_CACHE_SIZE > 1
2015-10-21 06:23:18 -07:00
const int slot = cache - > next_slot ;
2015-10-21 04:06:23 -07:00
# else
const int slot = 0 ;
# endif
2015-10-21 06:23:18 -07:00
cache - > index [ slot ] . klass = ( const void * ) inputklass ;
cache - > entry [ slot ] . func = ( const void * ) func ;
2015-11-09 03:45:04 -08:00
cache - > off [ slot ] . off = ( int ) ( ( long ) ( ( char * ) call - > data - ( char * ) obj ) ) ;
2016-08-15 06:44:41 -07:00
# if EFL_OBJECT_CALL_CACHE_SIZE > 1
cache - > next_slot = ( slot + 1 ) % EFL_OBJECT_CALL_CACHE_SIZE ;
2015-10-21 04:06:23 -07:00
# endif
}
# endif
2013-07-10 00:24:59 -07:00
return EINA_TRUE ;
2013-07-08 08:31:36 -07:00
}
2013-12-26 15:18:45 -08:00
if ( func - > src ! = NULL )
{
2014-05-08 04:44:47 -07:00
ERR ( " in %s:%d: you called a pure virtual func '%s' (%d) of class '%s'. " ,
2015-10-21 06:23:18 -07:00
file , line , func_name , cache - > op , klass - > desc - > name ) ;
2013-12-26 15:18:45 -08:00
return EINA_FALSE ;
}
2013-11-11 02:34:35 -08:00
end :
2013-07-08 08:31:36 -07:00
/* Try composite objects */
2013-11-11 02:34:35 -08:00
if ( is_obj )
2013-10-03 05:30:31 -07:00
{
2014-06-13 10:09:56 -07:00
Eina_List * itr ;
Eo * emb_obj_id ;
2015-11-09 03:45:04 -08:00
EINA_LIST_FOREACH ( obj - > composite_objects , itr , emb_obj_id )
2013-10-03 05:30:31 -07:00
{
2014-10-27 15:23:45 -07:00
_Eo_Object * emb_obj = _eo_obj_pointer_get ( ( Eo_Id ) emb_obj_id ) ;
2014-06-13 10:09:56 -07:00
2014-10-27 15:23:45 -07:00
if ( ! emb_obj )
continue ;
2013-10-03 05:30:31 -07:00
2016-05-18 10:12:39 -07:00
func = _vtable_func_get ( emb_obj - > vtable , cache - > op ) ;
2013-10-03 05:30:31 -07:00
if ( func = = NULL )
continue ;
2013-11-11 02:34:35 -08:00
if ( EINA_LIKELY ( func - > func & & func - > src ) )
2013-10-03 05:30:31 -07:00
{
2016-05-17 02:29:14 -07:00
call - > eo_id = _eo_obj_id_get ( emb_obj ) ;
2016-08-15 06:44:41 -07:00
call - > obj = _efl_ref ( emb_obj ) ;
2013-10-03 05:30:31 -07:00
call - > func = func - > func ;
2016-08-15 06:44:41 -07:00
call - > data = _efl_data_scope_get ( emb_obj , func - > src ) ;
2013-10-03 05:30:31 -07:00
2016-06-05 07:16:58 -07:00
/* We reffed it above, but no longer need/use it. */
2016-08-15 06:44:41 -07:00
_efl_unref ( obj ) ;
2016-06-05 07:16:58 -07:00
2013-10-03 05:30:31 -07:00
return EINA_TRUE ;
}
}
}
2013-11-11 02:34:35 -08:00
{
/* If it's a do_super call. */
2015-11-09 03:45:04 -08:00
if ( cur_klass )
2013-11-11 02:34:35 -08:00
{
2014-01-08 02:10:48 -08:00
ERR ( " in %s:%d: func '%s' (%d) could not be resolved for class '%s' for super of '%s'. " ,
2015-10-21 06:23:18 -07:00
file , line , func_name , cache - > op , main_klass - > desc - > name ,
2015-11-09 03:45:04 -08:00
cur_klass - > desc - > name ) ;
2013-11-11 02:34:35 -08:00
}
else
{
2014-01-08 03:11:20 -08:00
/* we should not be able to take this branch */
2014-01-08 02:10:48 -08:00
ERR ( " in %s:%d: func '%s' (%d) could not be resolved for class '%s'. " ,
2015-10-21 06:23:18 -07:00
file , line , func_name , cache - > op , main_klass - > desc - > name ) ;
2013-11-11 02:34:35 -08:00
}
}
2013-07-10 00:24:59 -07:00
return EINA_FALSE ;
2013-07-08 08:31:36 -07:00
}
2015-11-09 03:45:04 -08:00
EAPI void
2016-08-15 06:44:41 -07:00
_efl_object_call_end ( Efl_Object_Op_Call_Data * call )
2015-11-09 03:45:04 -08:00
{
if ( EINA_LIKELY ( ! ! call - > obj ) )
{
2016-08-15 06:44:41 -07:00
_efl_unref ( call - > obj ) ;
2015-11-09 03:45:04 -08:00
}
}
2015-10-09 04:06:09 -07:00
static inline Eina_Bool
_eo_api_func_equal ( const void * api_func1 , const void * api_func2 )
{
# ifndef _WIN32
return ( api_func1 = = api_func2 ) ;
# else
/* On Windows, DLL API's will be exported using the dllexport flag.
* When used by another library or executable , they will be declared
* using the dllimport flag . What happens really is that two symbols are
* created , at two different addresses . So it ' s impossible to match
* them . We fallback to plain string comparison based on the
* function name itself . Slow , but this should rarely happen .
*/
return ( api_func2 & & api_func1 & & ! strcmp ( api_func2 , api_func1 ) ) ;
# endif
}
2015-06-18 04:30:13 -07:00
/* api_func should be the pointer to the function on all platforms except windows,
* in which it should be the the name of the function ( string ) .
*/
2016-08-09 06:10:05 -07:00
static inline const Efl_Op_Description *
_eo_api_desc_get ( const void * api_func , const _Efl_Class * klass , const _Efl_Class * * extns )
2013-12-25 05:51:52 -08:00
{
2016-08-09 06:10:05 -07:00
const _Efl_Class * cur_klass ;
const _Efl_Class * * kls_itr = NULL ;
const Efl_Op_Description * op_desc ;
const Efl_Op_Description * op_descs ;
2013-12-25 05:51:52 -08:00
2013-11-07 15:42:42 -08:00
if ( klass )
2013-12-25 05:51:52 -08:00
{
2013-11-07 15:42:42 -08:00
for ( kls_itr = klass - > mro ; * kls_itr ; kls_itr + + )
2013-07-25 23:39:34 -07:00
{
2015-09-28 09:18:43 -07:00
unsigned int i ;
2013-11-07 15:42:42 -08:00
cur_klass = * kls_itr ;
2015-06-18 04:30:13 -07:00
op_descs = cur_klass - > desc - > ops . descs ;
2015-09-28 09:18:43 -07:00
for ( i = 0 , op_desc = op_descs ; i < cur_klass - > desc - > ops . count ; i + + , op_desc + + )
2013-11-07 15:42:42 -08:00
{
2015-10-09 04:06:09 -07:00
if ( _eo_api_func_equal ( op_desc - > api_func , api_func ) )
2015-06-18 05:44:51 -07:00
{
2015-09-30 00:37:31 -07:00
return op_desc ;
2015-06-18 05:44:51 -07:00
}
2015-09-30 00:37:31 -07:00
}
2013-11-07 15:42:42 -08:00
}
2013-10-03 05:30:31 -07:00
}
if ( extns )
{
for ( kls_itr = extns ; * kls_itr ; kls_itr + + )
{
cur_klass = * kls_itr ;
2015-06-18 04:30:13 -07:00
op_desc = _eo_api_desc_get ( api_func , cur_klass , NULL ) ;
2013-11-08 03:08:17 -08:00
if ( op_desc ) return op_desc ;
2013-10-03 05:30:31 -07:00
}
2013-12-25 05:51:52 -08:00
}
2013-12-25 07:14:55 -08:00
return NULL ;
}
2016-08-15 06:44:41 -07:00
EAPI Efl_Object_Op
_efl_object_api_op_id_get ( const void * api_func )
2013-12-25 07:14:55 -08:00
{
2015-09-28 09:18:43 -07:00
eina_spinlock_take ( & _ops_storage_lock ) ;
2015-10-09 04:06:09 -07:00
# ifndef _WIN32
2016-08-15 06:44:41 -07:00
Efl_Object_Op op = ( uintptr_t ) eina_hash_find ( _ops_storage , & api_func ) ;
2015-10-09 04:06:09 -07:00
# else
2016-08-15 06:44:41 -07:00
Efl_Object_Op op = ( uintptr_t ) eina_hash_find ( _ops_storage , api_func ) ;
2015-10-09 04:06:09 -07:00
# endif
2015-09-28 09:18:43 -07:00
eina_spinlock_release ( & _ops_storage_lock ) ;
2013-12-25 05:51:52 -08:00
2016-08-15 06:44:41 -07:00
if ( op = = EFL_NOOP )
2015-10-15 10:03:27 -07:00
{
ERR ( " Unable to resolve op for api func %p " , api_func ) ;
}
2015-09-28 09:18:43 -07:00
return op ;
2013-12-25 05:51:52 -08:00
}
2016-05-19 03:33:17 -07:00
/* klass is the klass we are working on. hierarchy_klass is the class whe should
* use when validating . */
2014-04-03 09:54:30 -07:00
static Eina_Bool
2016-08-15 06:44:41 -07:00
_eo_class_funcs_set ( Eo_Vtable * vtable , const Efl_Object_Ops * ops , const _Efl_Class * hierarchy_klass , const _Efl_Class * klass , Eina_Bool override_only )
2013-12-25 05:51:52 -08:00
{
2015-09-28 07:48:17 -07:00
unsigned int i ;
2013-07-24 15:08:37 -07:00
int op_id ;
2014-01-08 02:13:34 -08:00
const void * last_api_func ;
2016-08-09 06:10:05 -07:00
const Efl_Op_Description * op_desc ;
const Efl_Op_Description * op_descs ;
2013-12-25 05:51:52 -08:00
2016-05-19 03:33:17 -07:00
op_id = hierarchy_klass - > base_id ;
op_descs = ops - > descs ;
2013-12-25 05:51:52 -08:00
2014-01-08 02:13:34 -08:00
DBG ( " Set functions for class '%s':%p " , klass - > desc - > name , klass ) ;
2014-01-09 05:42:17 -08:00
if ( ! op_descs ) return EINA_TRUE ;
2014-01-08 02:13:34 -08:00
last_api_func = NULL ;
2016-05-19 03:33:17 -07:00
for ( i = 0 , op_desc = op_descs ; i < ops - > count ; i + + , op_desc + + )
2013-12-25 05:51:52 -08:00
{
2016-08-15 06:44:41 -07:00
Efl_Object_Op op = EFL_NOOP ;
2015-09-28 09:18:43 -07:00
if ( op_desc - > api_func = = NULL )
2014-01-08 02:13:34 -08:00
{
2015-09-28 09:18:43 -07:00
ERR ( " Class '%s': NULL API not allowed (NULL->%p '%s'). " ,
klass - > desc - > name , op_desc - > func , _eo_op_desc_name_get ( op_desc ) ) ;
2014-01-09 05:43:26 -08:00
return EINA_FALSE ;
2014-01-08 02:13:34 -08:00
}
2013-07-24 15:08:37 -07:00
2016-08-15 06:44:41 -07:00
if ( ( op_desc - > op_type = = EFL_OBJECT_OP_TYPE_REGULAR ) | | ( op_desc - > op_type = = EFL_OBJECT_OP_TYPE_CLASS ) )
2013-12-25 05:51:52 -08:00
{
2016-05-19 03:33:17 -07:00
if ( override_only )
{
ERR ( " Creation of new functions is not allowed when overriding an object's vtable. " ) ;
return EINA_FALSE ;
}
2015-10-09 04:06:09 -07:00
if ( _eo_api_func_equal ( op_desc - > api_func , last_api_func ) )
2014-01-08 02:13:34 -08:00
{
2015-09-28 09:18:43 -07:00
ERR ( " Class '%s': API previously defined (%p->%p '%s'). " ,
klass - > desc - > name , op_desc - > api_func , op_desc - > func , _eo_op_desc_name_get ( op_desc ) ) ;
2014-01-09 05:43:26 -08:00
return EINA_FALSE ;
2014-01-08 02:13:34 -08:00
}
2015-09-28 09:18:43 -07:00
op = op_id ;
eina_spinlock_take ( & _ops_storage_lock ) ;
2015-10-09 04:06:09 -07:00
# ifndef _WIN32
2015-09-28 09:18:43 -07:00
eina_hash_add ( _ops_storage , & op_desc - > api_func , ( void * ) ( uintptr_t ) op ) ;
2015-10-09 04:06:09 -07:00
# else
eina_hash_add ( _ops_storage , op_desc - > api_func , ( void * ) ( uintptr_t ) op ) ;
# endif
2015-09-28 09:18:43 -07:00
eina_spinlock_release ( & _ops_storage_lock ) ;
2013-07-24 15:08:37 -07:00
op_id + + ;
}
2016-08-15 06:44:41 -07:00
else if ( ( op_desc - > op_type = = EFL_OBJECT_OP_TYPE_REGULAR_OVERRIDE ) | | ( op_desc - > op_type = = EFL_OBJECT_OP_TYPE_CLASS_OVERRIDE ) )
2013-07-24 15:08:37 -07:00
{
2016-08-09 06:10:05 -07:00
const Efl_Op_Description * api_desc ;
2016-05-19 03:33:17 -07:00
if ( override_only )
{
api_desc = _eo_api_desc_get ( op_desc - > api_func , hierarchy_klass , NULL ) ;
}
else
{
api_desc = _eo_api_desc_get ( op_desc - > api_func , hierarchy_klass - > parent , hierarchy_klass - > extensions ) ;
}
2013-12-25 07:14:55 -08:00
if ( api_desc = = NULL )
2014-01-08 02:13:34 -08:00
{
2014-04-03 09:54:30 -07:00
ERR ( " Class '%s': Can't find api func description in class hierarchy (%p->%p) (%s). " ,
2016-05-19 03:33:17 -07:00
hierarchy_klass - > desc - > name , op_desc - > api_func , op_desc - > func , _eo_op_desc_name_get ( op_desc ) ) ;
2014-01-09 05:43:26 -08:00
return EINA_FALSE ;
2014-01-08 02:13:34 -08:00
}
2013-12-25 07:14:55 -08:00
2016-08-15 06:44:41 -07:00
op = _efl_object_api_op_id_get ( op_desc - > api_func ) ;
2015-09-28 09:18:43 -07:00
}
2016-08-15 06:44:41 -07:00
if ( op = = EFL_NOOP )
2015-09-28 09:18:43 -07:00
{
2016-08-15 06:44:41 -07:00
ERR ( " Class '%s': Invalid op 'EFL_NOOP' (%p->%p '%s'). " ,
2015-09-28 09:18:43 -07:00
klass - > desc - > name , op_desc - > api_func , op_desc - > func , _eo_op_desc_name_get ( op_desc ) ) ;
return EINA_FALSE ;
2013-12-25 05:51:52 -08:00
}
2013-07-24 15:08:37 -07:00
2015-09-28 09:18:43 -07:00
DBG ( " %p->%p '%s' " , op_desc - > api_func , op_desc - > func , _eo_op_desc_name_get ( op_desc ) ) ;
2014-01-08 02:13:34 -08:00
2016-05-19 03:33:17 -07:00
if ( ! _vtable_func_set ( vtable , klass , op , op_desc - > func ) )
2014-01-09 05:43:26 -08:00
return EINA_FALSE ;
2014-01-08 02:13:34 -08:00
last_api_func = op_desc - > api_func ;
2013-12-25 05:51:52 -08:00
}
2014-01-09 05:42:17 -08:00
return EINA_TRUE ;
2013-12-25 05:51:52 -08:00
}
2013-08-01 00:47:21 -07:00
EAPI Eo *
2016-08-15 06:44:41 -07:00
_efl_add_internal_start ( const char * file , int line , const Efl_Class * klass_id , Eo * parent_id , Eina_Bool ref EINA_UNUSED , Eina_Bool is_fallback )
2013-08-01 00:47:21 -07:00
{
2013-12-26 15:00:11 -08:00
_Eo_Object * obj ;
2016-03-29 06:47:22 -07:00
Eo_Stack_Frame * fptr = NULL ;
if ( is_fallback )
{
2016-08-15 06:44:41 -07:00
fptr = _efl_add_fallback_stack_push ( NULL ) ;
2016-03-29 06:47:22 -07:00
}
2013-12-26 15:00:11 -08:00
2013-12-26 11:42:18 -08:00
EO_CLASS_POINTER_RETURN_VAL ( klass_id , klass , NULL ) ;
2013-08-01 00:47:21 -07:00
if ( parent_id )
{
EO_OBJ_POINTER_RETURN_VAL ( parent_id , parent , NULL ) ;
}
2016-08-15 06:44:41 -07:00
if ( EINA_UNLIKELY ( klass - > desc - > type ! = EFL_CLASS_TYPE_REGULAR ) )
2013-08-01 00:47:21 -07:00
{
ERR ( " in %s:%d: Class '%s' is not instantiate-able. Aborting. " , file , line , klass - > desc - > name ) ;
return NULL ;
}
2013-12-26 15:00:11 -08:00
eina_spinlock_take ( & klass - > objects . trash_lock ) ;
obj = eina_trash_pop ( & klass - > objects . trash ) ;
if ( obj )
{
memset ( obj , 0 , klass - > obj_size ) ;
klass - > objects . trash_count - - ;
}
else
{
obj = calloc ( 1 , klass - > obj_size ) ;
}
eina_spinlock_release ( & klass - > objects . trash_lock ) ;
2013-08-01 00:47:21 -07:00
obj - > refcount + + ;
obj - > klass = klass ;
2016-05-18 10:12:39 -07:00
obj - > vtable = & klass - > vtable ;
2013-08-01 00:47:21 -07:00
# ifndef HAVE_EO_ID
2015-05-28 08:49:13 -07:00
EINA_MAGIC_SET ( ( Eo_Header * ) obj , EO_EINA_MAGIC ) ;
2013-08-01 00:47:21 -07:00
# endif
2014-09-25 07:51:17 -07:00
obj - > header . id = _eo_id_allocate ( obj ) ;
2016-05-17 02:29:14 -07:00
Eo * eo_id = _eo_obj_id_get ( obj ) ;
2013-08-01 00:47:21 -07:00
_eo_condtor_reset ( obj ) ;
2016-08-15 06:44:41 -07:00
efl_ref ( eo_id ) ;
2013-12-26 15:00:11 -08:00
2016-08-15 06:44:41 -07:00
/* Reference for the parent if is_ref is done in _efl_add_end */
2016-08-09 06:10:05 -07:00
efl_parent_set ( eo_id , parent_id ) ;
2013-12-26 12:11:48 -08:00
2015-05-19 03:41:27 -07:00
/* eo_id can change here. Freeing is done on the resolved object. */
2016-08-09 06:10:05 -07:00
eo_id = efl_constructor ( eo_id ) ;
2015-05-19 03:41:27 -07:00
if ( ! eo_id )
{
ERR ( " Object of class '%s' - Error while constructing object " ,
klass - > desc - > name ) ;
2016-05-18 05:29:45 -07:00
/* We have two refs at this point. */
2016-08-15 06:44:41 -07:00
_efl_unref ( obj ) ;
2016-08-09 06:10:05 -07:00
efl_del ( ( Eo * ) obj - > header . id ) ;
2015-05-19 03:41:27 -07:00
return NULL ;
}
2016-05-18 05:29:45 -07:00
else if ( eo_id ! = _eo_obj_id_get ( obj ) )
{
2016-07-12 02:26:23 -07:00
EO_OBJ_POINTER_RETURN_VAL ( eo_id , new_obj , NULL ) ;
2016-05-18 05:29:45 -07:00
/* We have two refs at this point. */
2016-08-15 06:44:41 -07:00
_efl_unref ( obj ) ;
2016-08-09 06:10:05 -07:00
efl_del ( ( Eo * ) obj - > header . id ) ;
2016-07-12 02:26:23 -07:00
2016-08-15 06:44:41 -07:00
_efl_ref ( new_obj ) ;
2016-07-12 02:26:23 -07:00
}
2016-05-18 05:29:45 -07:00
2016-03-29 06:47:22 -07:00
if ( is_fallback )
{
fptr - > obj = eo_id ;
}
2014-09-25 07:51:17 -07:00
return eo_id ;
2013-08-01 00:47:21 -07:00
}
2015-05-20 06:56:45 -07:00
static Eo *
2016-08-15 06:44:41 -07:00
_efl_add_internal_end ( Eo * eo_id , Eo * finalized_id )
2013-08-01 00:47:21 -07:00
{
2015-11-09 03:45:04 -08:00
EO_OBJ_POINTER_RETURN_VAL ( eo_id , obj , NULL ) ;
2014-04-14 02:36:09 -07:00
2015-11-09 03:45:04 -08:00
if ( ! obj - > condtor_done )
2013-08-01 00:47:21 -07:00
{
2016-08-09 06:10:05 -07:00
const _Efl_Class * klass = obj - > klass ;
2015-10-15 10:38:32 -07:00
2015-10-16 02:08:33 -07:00
ERR ( " Object of class '%s' - Not all of the object constructors have been executed. " ,
klass - > desc - > name ) ;
goto cleanup ;
}
2015-05-20 06:56:45 -07:00
2015-11-09 03:45:04 -08:00
if ( ! finalized_id )
2015-10-16 02:08:33 -07:00
{
// XXX: Given EFL usage of objects, construction is a perfectly valid thing
// to do. we shouldn't complain about it as handling a NULL obj creation is
// the job of the caller. a perfect example here is ecore_con and ecore_ipc
// where you create a con or ipc obj then set up type/destination/port and
// the finalize of the constructor does the actual connect and thus this
// fails or succeeds based on if service is there.
//
// until there is a better solution - don't complain here.
//
// ERR("Object of class '%s' - Finalizing the object failed.",
// klass->desc->name);
goto cleanup ;
2013-08-01 00:47:21 -07:00
}
2015-11-09 03:45:04 -08:00
obj - > finalized = EINA_TRUE ;
2014-08-29 01:55:02 -07:00
2016-08-15 06:44:41 -07:00
_efl_unref ( obj ) ;
2013-12-26 15:00:11 -08:00
return ( Eo * ) eo_id ;
2015-05-20 06:56:45 -07:00
cleanup :
2016-08-15 06:44:41 -07:00
_efl_unref ( obj ) ;
2016-08-09 06:10:05 -07:00
efl_del ( ( Eo * ) obj - > header . id ) ;
2015-05-20 06:56:45 -07:00
return NULL ;
2013-08-01 00:47:21 -07:00
}
Eo: Remove GCCism and make it more portable.
This affects eo_do() and eo_add() that used to use the ({}) GCCism.
Following a discussion with Peter de Ridder after my talk at FOSDEM,
we've decided to reopen the GCCism (works with other gcc compatible
compilers like clang and intelc) discussion, and after a bit of back and
forth it was decided to make things more portable, at the cost of ease
of use.
For example:
if (eo_do(obj, visible_get()))
is no longer allowed, the portable alternative
Eina_Bool tmp;
if (eo_do_ret(obj, tmp, visible_get()))
is to be used instead.
However:
eo_do(obj, a = a_get(), b = b_get(), bool_set(!bool_get))
are still allowed and OK.
eo_do(obj, if (a_get()) return;);
is no longer allowed, but:
eo_do(obj, if (a_get()) something());
is still allowed.
For clarity, this commit only incorporates the Eo changes, and not the
EFL changes to make the efl conform with this change.
Thanks again to Peter de Ridder for triggering this important discussion
which led to this change.
2015-02-23 08:06:40 -08:00
EAPI Eo *
2016-08-15 06:44:41 -07:00
_efl_add_end ( Eo * eo_id , Eina_Bool is_ref , Eina_Bool is_fallback )
Eo: Remove GCCism and make it more portable.
This affects eo_do() and eo_add() that used to use the ({}) GCCism.
Following a discussion with Peter de Ridder after my talk at FOSDEM,
we've decided to reopen the GCCism (works with other gcc compatible
compilers like clang and intelc) discussion, and after a bit of back and
forth it was decided to make things more portable, at the cost of ease
of use.
For example:
if (eo_do(obj, visible_get()))
is no longer allowed, the portable alternative
Eina_Bool tmp;
if (eo_do_ret(obj, tmp, visible_get()))
is to be used instead.
However:
eo_do(obj, a = a_get(), b = b_get(), bool_set(!bool_get))
are still allowed and OK.
eo_do(obj, if (a_get()) return;);
is no longer allowed, but:
eo_do(obj, if (a_get()) something());
is still allowed.
For clarity, this commit only incorporates the Eo changes, and not the
EFL changes to make the efl conform with this change.
Thanks again to Peter de Ridder for triggering this important discussion
which led to this change.
2015-02-23 08:06:40 -08:00
{
2016-08-09 06:10:05 -07:00
Eo * ret = efl_finalize ( eo_id ) ;
2016-08-15 06:44:41 -07:00
ret = _efl_add_internal_end ( eo_id , ret ) ;
2015-11-09 03:45:04 -08:00
2016-08-09 06:10:05 -07:00
if ( is_ref & & efl_parent_get ( eo_id ) )
2016-07-12 02:34:54 -07:00
{
2016-08-15 06:44:41 -07:00
efl_ref ( eo_id ) ;
2016-07-12 02:34:54 -07:00
}
2016-03-29 06:47:22 -07:00
if ( is_fallback )
{
2016-08-15 06:44:41 -07:00
_efl_add_fallback_stack_pop ( ) ;
2016-03-29 06:47:22 -07:00
}
Eo: Remove GCCism and make it more portable.
This affects eo_do() and eo_add() that used to use the ({}) GCCism.
Following a discussion with Peter de Ridder after my talk at FOSDEM,
we've decided to reopen the GCCism (works with other gcc compatible
compilers like clang and intelc) discussion, and after a bit of back and
forth it was decided to make things more portable, at the cost of ease
of use.
For example:
if (eo_do(obj, visible_get()))
is no longer allowed, the portable alternative
Eina_Bool tmp;
if (eo_do_ret(obj, tmp, visible_get()))
is to be used instead.
However:
eo_do(obj, a = a_get(), b = b_get(), bool_set(!bool_get))
are still allowed and OK.
eo_do(obj, if (a_get()) return;);
is no longer allowed, but:
eo_do(obj, if (a_get()) something());
is still allowed.
For clarity, this commit only incorporates the Eo changes, and not the
EFL changes to make the efl conform with this change.
Thanks again to Peter de Ridder for triggering this important discussion
which led to this change.
2015-02-23 08:06:40 -08:00
return ret ;
}
2013-07-18 00:10:07 -07:00
/*****************************************************************************/
2016-08-09 06:10:05 -07:00
EAPI const Efl_Class *
2016-08-15 06:44:41 -07:00
efl_class_get ( const Eo * eo_id )
2012-04-05 08:31:15 -07:00
{
2013-12-26 14:46:50 -08:00
if ( _eo_is_a_class ( eo_id ) )
2013-09-26 15:13:31 -07:00
{
2013-12-26 14:46:50 -08:00
EO_CLASS_POINTER_RETURN_VAL ( eo_id , _klass , NULL ) ;
2016-08-10 07:23:04 -07:00
return EFL_CLASS_CLASS ;
2013-09-26 15:13:31 -07:00
}
2013-12-26 14:46:50 -08:00
EO_OBJ_POINTER_RETURN_VAL ( eo_id , obj , NULL ) ;
2012-04-23 01:10:04 -07:00
2016-03-04 06:05:57 -08:00
return _eo_class_id_get ( obj - > klass ) ;
2012-04-05 08:31:15 -07:00
}
EAPI const char *
2016-08-15 06:44:41 -07:00
efl_class_name_get ( const Efl_Class * eo_id )
2012-04-05 08:31:15 -07:00
{
2016-08-09 06:10:05 -07:00
const _Efl_Class * klass ;
2013-09-26 15:13:00 -07:00
2013-12-26 14:46:50 -08:00
if ( _eo_is_a_class ( eo_id ) )
2013-09-26 15:13:00 -07:00
{
2013-12-26 14:46:50 -08:00
EO_CLASS_POINTER_RETURN_VAL ( eo_id , _klass , NULL ) ;
2013-09-26 15:13:00 -07:00
klass = _klass ;
}
2015-10-15 04:56:15 -07:00
else
2013-09-26 15:13:00 -07:00
{
2013-12-26 14:46:50 -08:00
EO_OBJ_POINTER_RETURN_VAL ( eo_id , obj , NULL ) ;
2013-09-26 15:13:00 -07:00
klass = obj - > klass ;
}
2012-04-23 01:10:04 -07:00
2012-04-05 08:31:15 -07:00
return klass - > desc - > name ;
}
2016-05-19 03:33:17 -07:00
static void
_vtable_init ( Eo_Vtable * vtable , size_t size )
{
vtable - > size = size ;
2016-05-23 00:36:08 -07:00
vtable - > chain = calloc ( vtable - > size , sizeof ( * vtable - > chain ) ) ;
2016-05-19 03:33:17 -07:00
}
2012-04-05 08:31:15 -07:00
static void
2016-08-09 06:10:05 -07:00
_eo_class_base_op_init ( _Efl_Class * klass )
2012-04-05 08:31:15 -07:00
{
2016-08-09 06:10:05 -07:00
const Efl_Class_Description * desc = klass - > desc ;
2012-04-05 08:31:15 -07:00
2012-07-10 07:01:45 -07:00
klass - > base_id = _eo_ops_last_id ;
_eo_ops_last_id + = desc - > ops . count + 1 ;
2016-05-19 03:33:17 -07:00
_vtable_init ( & klass - > vtable , DICH_CHAIN1 ( _eo_ops_last_id ) + 1 ) ;
2012-04-05 08:31:15 -07:00
}
2013-01-18 08:57:57 -08:00
# ifdef EO_DEBUG
2012-06-14 03:29:39 -07:00
static Eina_Bool
2016-08-09 06:10:05 -07:00
_eo_class_mro_has ( const _Efl_Class * klass , const _Efl_Class * find )
2012-06-14 03:29:39 -07:00
{
2016-08-09 06:10:05 -07:00
const _Efl_Class * * itr ;
2012-06-14 03:29:39 -07:00
for ( itr = klass - > mro ; * itr ; itr + + )
{
if ( * itr = = find )
{
return EINA_TRUE ;
}
}
return EINA_FALSE ;
}
# endif
2013-06-17 14:38:04 -07:00
static Eina_List *
_eo_class_list_remove_duplicates ( Eina_List * list )
{
Eina_List * itr1 , * itr2 , * itr2n ;
itr1 = eina_list_last ( list ) ;
while ( itr1 )
{
itr2 = eina_list_prev ( itr1 ) ;
while ( itr2 )
{
itr2n = eina_list_prev ( itr2 ) ;
if ( eina_list_data_get ( itr1 ) = = eina_list_data_get ( itr2 ) )
{
list = eina_list_remove_list ( list , itr2 ) ;
}
itr2 = itr2n ;
}
itr1 = eina_list_prev ( itr1 ) ;
}
return list ;
}
2012-04-11 00:05:14 -07:00
static Eina_List *
2016-08-09 06:10:05 -07:00
_eo_class_mro_add ( Eina_List * mro , const _Efl_Class * klass )
2012-04-11 00:05:14 -07:00
{
if ( ! klass )
2013-06-17 14:41:02 -07:00
return mro ;
2012-04-11 00:05:14 -07:00
mro = eina_list_append ( mro , klass ) ;
2013-06-17 14:41:02 -07:00
/* Recursively add MIXINS extensions. */
2012-04-11 00:05:14 -07:00
{
2016-08-09 06:10:05 -07:00
const _Efl_Class * * extn_itr ;
2012-06-13 04:39:02 -07:00
for ( extn_itr = klass - > extensions ; * extn_itr ; extn_itr + + )
2012-04-11 00:05:14 -07:00
{
2016-08-09 06:10:05 -07:00
const _Efl_Class * extn = * extn_itr ;
2016-08-15 06:44:41 -07:00
if ( extn - > desc - > type = = EFL_CLASS_TYPE_MIXIN )
2013-06-17 14:41:02 -07:00
mro = _eo_class_mro_add ( mro , extn ) ;
2012-04-19 01:52:15 -07:00
}
}
2013-06-17 14:41:02 -07:00
mro = _eo_class_mro_add ( mro , klass - > parent ) ;
return mro ;
}
static Eina_List *
2016-08-09 06:10:05 -07:00
_eo_class_mro_init ( const Efl_Class_Description * desc , const _Efl_Class * parent , Eina_List * extensions )
2013-06-17 14:41:02 -07:00
{
Eina_List * mro = NULL ;
Eina_List * extn_itr = NULL ;
Eina_List * extn_pos = NULL ;
2016-08-09 06:10:05 -07:00
const _Efl_Class * extn = NULL ;
2013-06-17 14:41:02 -07:00
/* Add MIXINS extensions. */
EINA_LIST_FOREACH ( extensions , extn_itr , extn )
2012-04-19 01:52:15 -07:00
{
2016-08-15 06:44:41 -07:00
if ( extn - > desc - > type ! = EFL_CLASS_TYPE_MIXIN )
2013-06-17 14:41:02 -07:00
continue ;
2012-04-19 01:52:15 -07:00
2013-06-17 14:41:02 -07:00
mro = _eo_class_mro_add ( mro , extn ) ;
extn_pos = eina_list_append ( extn_pos , eina_list_last ( mro ) ) ;
}
/* Check if we can create a consistent mro */
{
2012-04-19 01:52:15 -07:00
Eina_List * itr = extn_pos ;
2013-06-17 14:41:02 -07:00
EINA_LIST_FOREACH ( extensions , extn_itr , extn )
2012-04-19 01:52:15 -07:00
{
2016-08-15 06:44:41 -07:00
if ( extn - > desc - > type ! = EFL_CLASS_TYPE_MIXIN )
2012-06-13 04:39:02 -07:00
continue ;
2012-04-19 01:52:15 -07:00
/* Get the first one after the extension. */
Eina_List * extn_list = eina_list_next ( eina_list_data_get ( itr ) ) ;
/* If we found the extension again. */
2012-06-13 04:39:02 -07:00
if ( eina_list_data_find_list ( extn_list , extn ) )
2012-04-19 01:52:15 -07:00
{
eina_list_free ( mro ) ;
2013-06-17 14:41:02 -07:00
eina_list_free ( extn_pos ) ;
ERR ( " Cannot create a consistent method resolution order for class '%s' because of '%s'. " , desc - > name , extn - > desc - > name ) ;
2012-04-19 01:52:15 -07:00
return NULL ;
}
itr = eina_list_next ( itr ) ;
2012-04-11 00:05:14 -07:00
}
}
2012-12-14 12:03:25 -08:00
eina_list_free ( extn_pos ) ;
2012-04-19 01:52:15 -07:00
2013-06-17 14:41:02 -07:00
mro = _eo_class_mro_add ( mro , parent ) ;
2013-06-17 14:38:04 -07:00
mro = _eo_class_list_remove_duplicates ( mro ) ;
2013-06-17 14:41:02 -07:00
/* Will be replaced with the actual class pointer */
mro = eina_list_prepend ( mro , NULL ) ;
2012-04-11 00:05:14 -07:00
2013-06-17 14:41:02 -07:00
return mro ;
2012-04-11 00:05:14 -07:00
}
2012-04-05 08:31:15 -07:00
static void
2016-08-09 06:10:05 -07:00
_eo_class_constructor ( _Efl_Class * klass )
2012-04-05 08:31:15 -07:00
{
klass - > constructed = EINA_TRUE ;
2012-04-11 00:05:14 -07:00
if ( klass - > desc - > class_constructor )
2013-07-29 14:52:46 -07:00
klass - > desc - > class_constructor ( _eo_class_id_get ( klass ) ) ;
2012-04-05 08:31:15 -07:00
}
2012-04-23 01:09:42 -07:00
static void
2016-08-09 06:10:05 -07:00
eo_class_free ( _Efl_Class * klass )
2012-04-16 05:36:42 -07:00
{
2013-09-11 00:08:06 -07:00
void * data ;
2013-09-10 19:23:50 -07:00
2012-04-16 05:36:42 -07:00
if ( klass - > constructed )
{
if ( klass - > desc - > class_destructor )
2013-04-18 04:19:02 -07:00
klass - > desc - > class_destructor ( _eo_class_id_get ( klass ) ) ;
2012-04-16 05:36:42 -07:00
2016-05-19 03:33:17 -07:00
_vtable_func_clean_all ( & klass - > vtable ) ;
2012-04-16 05:36:42 -07:00
}
2013-09-11 00:08:06 -07:00
EINA_TRASH_CLEAN ( & klass - > objects . trash , data )
2013-09-27 03:13:14 -07:00
free ( data ) ;
2013-09-10 19:23:50 -07:00
2013-09-11 00:08:06 -07:00
EINA_TRASH_CLEAN ( & klass - > iterators . trash , data )
2013-09-27 03:13:14 -07:00
free ( data ) ;
2013-09-11 00:08:06 -07:00
2013-10-10 01:26:02 -07:00
eina_spinlock_free ( & klass - > objects . trash_lock ) ;
eina_spinlock_free ( & klass - > iterators . trash_lock ) ;
2013-09-10 19:23:50 -07:00
2012-04-16 05:36:42 -07:00
free ( klass ) ;
}
2012-06-13 04:39:12 -07:00
/* Not really called, just used for the ptr... */
static void
2016-08-16 08:28:33 -07:00
_eo_class_isa_func ( Eo * eo_id EINA_UNUSED , void * class_data EINA_UNUSED )
2012-06-13 04:39:12 -07:00
{
/* Do nonthing. */
}
2016-04-23 20:00:37 -07:00
static inline void
_eo_classes_release ( void )
{
# ifdef HAVE_MMAP
size_t size ;
2016-08-09 06:10:05 -07:00
size = _eo_classes_alloc * sizeof ( _Efl_Class * ) ;
2016-04-23 20:00:37 -07:00
if ( _eo_classes ) munmap ( _eo_classes , size ) ;
# else
free ( _eo_classes ) ;
# endif
_eo_classes = NULL ;
_eo_classes_last_id = 0 ;
_eo_classes_alloc = 0 ;
}
static inline void
_eo_classes_expand ( void )
{
unsigned char * ptr ;
size_t newsize , psize ;
_eo_classes_last_id + + ;
if ( _eo_classes_last_id < = _eo_classes_alloc ) return ;
2016-08-09 06:10:05 -07:00
psize = _eo_classes_alloc * sizeof ( _Efl_Class * ) ;
2016-04-23 20:00:37 -07:00
# ifdef HAVE_MMAP
2016-08-09 06:10:05 -07:00
_eo_classes_alloc + = ( MEM_PAGE_SIZE / sizeof ( _Efl_Class * ) ) ;
newsize = _eo_classes_alloc * sizeof ( _Efl_Class * ) ;
2016-04-23 20:00:37 -07:00
ptr = mmap ( NULL , newsize , PROT_READ | PROT_WRITE ,
MAP_PRIVATE | MAP_ANON , - 1 , 0 ) ;
if ( ptr = = MAP_FAILED )
{
ERR ( " mmap of eo class table region failed! " ) ;
abort ( ) ;
}
if ( psize > 0 ) memcpy ( ptr , _eo_classes , psize ) ;
if ( _eo_classes ) munmap ( _eo_classes , psize ) ;
# else
_eo_classes_alloc + = 128 ;
2016-08-09 06:10:05 -07:00
newsize = _eo_classes_alloc * sizeof ( _Efl_Class * ) ;
2016-04-23 20:00:37 -07:00
ptr = realloc ( _eo_classes , newsize ) ;
if ( ! ptr )
{
ERR ( " realloc of eo class table region faile!! " ) ;
abort ( ) ;
}
# endif
memset ( ptr + psize , 0 , newsize - psize ) ;
2016-08-09 06:10:05 -07:00
_eo_classes = ( _Efl_Class * * ) ptr ;
2016-04-23 20:00:37 -07:00
}
2016-08-09 06:10:05 -07:00
EAPI const Efl_Class *
2016-08-15 06:44:41 -07:00
efl_class_new ( const Efl_Class_Description * desc , const Efl_Class * parent_id , . . . )
2012-04-05 08:31:15 -07:00
{
2016-08-09 06:10:05 -07:00
_Efl_Class * klass ;
2012-04-05 08:31:15 -07:00
va_list p_list ;
2013-06-17 14:48:22 -07:00
size_t extn_sz , mro_sz , mixins_sz ;
2013-06-17 14:47:15 -07:00
Eina_List * extn_list , * mro , * mixins ;
2012-04-05 08:31:15 -07:00
2014-02-19 01:13:47 -08:00
EINA_SAFETY_ON_NULL_RETURN_VAL ( desc , NULL ) ;
EINA_SAFETY_ON_NULL_RETURN_VAL ( desc - > name , NULL ) ;
2016-08-09 06:10:05 -07:00
_Efl_Class * parent = _eo_class_pointer_get ( parent_id ) ;
2013-09-26 08:06:46 -07:00
# ifndef HAVE_EO_ID
2015-05-28 08:49:13 -07:00
if ( parent & & ! EINA_MAGIC_CHECK ( ( Eo_Header * ) parent , EO_CLASS_EINA_MAGIC ) )
2012-04-23 01:10:04 -07:00
{
2015-05-28 08:49:13 -07:00
EINA_MAGIC_FAIL ( ( Eo_Header * ) parent , EO_CLASS_EINA_MAGIC ) ;
2012-04-23 01:10:04 -07:00
return NULL ;
}
2013-09-26 08:06:46 -07:00
# endif
2012-04-23 01:10:04 -07:00
2012-04-19 04:30:10 -07:00
/* Check restrictions on Interface types. */
2016-08-15 06:44:41 -07:00
if ( desc - > type = = EFL_CLASS_TYPE_INTERFACE )
2012-04-19 04:30:10 -07:00
{
2012-04-23 01:10:06 -07:00
EINA_SAFETY_ON_FALSE_RETURN_VAL ( ! desc - > data_size , NULL ) ;
2012-04-19 04:30:10 -07:00
}
2013-06-17 14:41:45 -07:00
/* Check parent */
if ( parent )
{
/* Verify the inheritance is allowed. */
switch ( desc - > type )
{
2016-08-15 06:44:41 -07:00
case EFL_CLASS_TYPE_REGULAR :
case EFL_CLASS_TYPE_REGULAR_NO_INSTANT :
if ( ( parent - > desc - > type ! = EFL_CLASS_TYPE_REGULAR ) & &
( parent - > desc - > type ! = EFL_CLASS_TYPE_REGULAR_NO_INSTANT ) )
2013-06-17 14:41:45 -07:00
{
ERR ( " Regular classes ('%s') aren't allowed to inherit from non-regular classes ('%s'). " ,
desc - > name , parent - > desc - > name ) ;
return NULL ;
}
break ;
2016-08-15 06:44:41 -07:00
case EFL_CLASS_TYPE_INTERFACE :
case EFL_CLASS_TYPE_MIXIN :
if ( ( parent - > desc - > type ! = EFL_CLASS_TYPE_INTERFACE ) & &
( parent - > desc - > type ! = EFL_CLASS_TYPE_MIXIN ) )
2013-06-17 14:41:45 -07:00
{
ERR ( " Non-regular classes ('%s') aren't allowed to inherit from regular classes ('%s'). " ,
desc - > name , parent - > desc - > name ) ;
return NULL ;
}
break ;
}
}
2013-06-17 14:35:48 -07:00
/* Build class extensions list */
2012-04-05 08:31:15 -07:00
{
2013-06-17 14:35:48 -07:00
DBG ( " Started building extensions list for class '%s' " , desc - > name ) ;
extn_list = NULL ;
2016-08-09 06:10:05 -07:00
const _Efl_Class * extn = NULL ;
2013-09-27 02:50:06 -07:00
const Eo_Id * extn_id = NULL ;
2013-06-17 14:35:48 -07:00
va_start ( p_list , parent_id ) ;
2012-04-05 08:31:15 -07:00
2013-09-27 02:50:06 -07:00
extn_id = va_arg ( p_list , Eo_Id * ) ;
2013-04-18 04:19:02 -07:00
while ( extn_id )
2012-04-05 08:31:15 -07:00
{
2016-08-09 06:10:05 -07:00
extn = _eo_class_pointer_get ( ( Efl_Class * ) extn_id ) ;
2012-04-05 08:31:15 -07:00
switch ( extn - > desc - > type )
{
2016-08-15 06:44:41 -07:00
case EFL_CLASS_TYPE_REGULAR_NO_INSTANT :
case EFL_CLASS_TYPE_REGULAR :
case EFL_CLASS_TYPE_INTERFACE :
case EFL_CLASS_TYPE_MIXIN :
2012-06-13 04:39:02 -07:00
extn_list = eina_list_append ( extn_list , extn ) ;
2012-04-05 08:31:15 -07:00
break ;
}
2013-09-27 02:50:06 -07:00
extn_id = va_arg ( p_list , Eo_Id * ) ;
2012-04-05 08:31:15 -07:00
}
2012-06-13 04:39:02 -07:00
2013-06-17 14:35:48 -07:00
va_end ( p_list ) ;
2013-06-17 14:38:04 -07:00
extn_list = _eo_class_list_remove_duplicates ( extn_list ) ;
2016-08-09 06:10:05 -07:00
extn_sz = sizeof ( _Efl_Class * ) * ( eina_list_count ( extn_list ) + 1 ) ;
2013-06-17 14:35:48 -07:00
DBG ( " Finished building extensions list for class '%s' " , desc - > name ) ;
}
2013-06-17 14:41:02 -07:00
/* Prepare mro list */
{
DBG ( " Started building MRO list for class '%s' " , desc - > name ) ;
mro = _eo_class_mro_init ( desc , parent , extn_list ) ;
if ( ! mro )
{
eina_list_free ( extn_list ) ;
return NULL ;
}
2016-08-09 06:10:05 -07:00
mro_sz = sizeof ( _Efl_Class * ) * ( eina_list_count ( mro ) + 1 ) ;
2013-06-17 14:41:02 -07:00
DBG ( " Finished building MRO list for class '%s' " , desc - > name ) ;
}
2013-06-17 14:48:22 -07:00
/* Prepare mixins list */
{
Eina_List * itr ;
2016-08-09 06:10:05 -07:00
const _Efl_Class * kls_itr ;
2013-06-17 14:48:22 -07:00
DBG ( " Started building Mixins list for class '%s' " , desc - > name ) ;
mixins = NULL ;
EINA_LIST_FOREACH ( mro , itr , kls_itr )
{
2016-08-15 06:44:41 -07:00
if ( ( kls_itr ) & & ( kls_itr - > desc - > type = = EFL_CLASS_TYPE_MIXIN ) & &
2013-06-17 14:48:22 -07:00
( kls_itr - > desc - > data_size > 0 ) )
mixins = eina_list_append ( mixins , kls_itr ) ;
}
mixins_sz = sizeof ( Eo_Extension_Data_Offset ) * ( eina_list_count ( mixins ) + 1 ) ;
2016-08-15 06:44:41 -07:00
if ( ( desc - > type = = EFL_CLASS_TYPE_MIXIN ) & & ( desc - > data_size > 0 ) )
2013-06-17 14:48:22 -07:00
mixins_sz + = sizeof ( Eo_Extension_Data_Offset ) ;
DBG ( " Finished building Mixins list for class '%s' " , desc - > name ) ;
}
klass = calloc ( 1 , _eo_class_sz + extn_sz + mro_sz + mixins_sz ) ;
2013-09-27 03:13:14 -07:00
# ifndef HAVE_EO_ID
2015-05-28 08:49:13 -07:00
EINA_MAGIC_SET ( ( Eo_Header * ) klass , EO_CLASS_EINA_MAGIC ) ;
2013-09-26 08:06:46 -07:00
# endif
2013-10-10 01:26:02 -07:00
eina_spinlock_new ( & klass - > objects . trash_lock ) ;
eina_spinlock_new ( & klass - > iterators . trash_lock ) ;
2013-06-17 14:35:48 -07:00
klass - > parent = parent ;
klass - > desc = desc ;
2016-08-09 06:10:05 -07:00
klass - > extensions = ( const _Efl_Class * * ) ( ( char * ) klass + _eo_class_sz ) ;
klass - > mro = ( const _Efl_Class * * ) ( ( char * ) klass - > extensions + extn_sz ) ;
2013-06-17 14:48:22 -07:00
klass - > extn_data_off = ( Eo_Extension_Data_Offset * ) ( ( char * ) klass - > mro + mro_sz ) ;
2013-06-17 14:41:45 -07:00
if ( klass - > parent )
{
/* FIXME: Make sure this alignment is enough. */
klass - > data_offset = klass - > parent - > data_offset +
EO_ALIGN_SIZE ( klass - > parent - > desc - > data_size ) ;
}
2015-10-12 08:12:36 -07:00
else
{
/* Data starts after the object size. */
klass - > data_offset = _eo_sz ;
}
2013-06-17 14:41:02 -07:00
mro = eina_list_remove ( mro , NULL ) ;
mro = eina_list_prepend ( mro , klass ) ;
2016-08-15 06:44:41 -07:00
if ( ( desc - > type = = EFL_CLASS_TYPE_MIXIN ) & & ( desc - > data_size > 0 ) )
2013-06-17 14:48:22 -07:00
mixins = eina_list_prepend ( mixins , klass ) ;
2012-06-13 04:39:02 -07:00
2013-06-17 14:35:48 -07:00
/* Copy the extensions and free the list */
{
2016-08-09 06:10:05 -07:00
const _Efl_Class * extn = NULL ;
const _Efl_Class * * extn_itr = klass - > extensions ;
2012-06-13 04:39:02 -07:00
EINA_LIST_FREE ( extn_list , extn )
{
* ( extn_itr + + ) = extn ;
2013-06-17 14:35:48 -07:00
DBG ( " Added '%s' extension " , extn - > desc - > name ) ;
2012-06-13 04:39:02 -07:00
}
2013-06-17 14:35:48 -07:00
* ( extn_itr ) = NULL ;
2012-04-05 08:31:15 -07:00
}
2013-06-17 14:48:22 -07:00
/* Copy the mro and free the list. */
2013-06-17 14:41:02 -07:00
{
2016-08-09 06:10:05 -07:00
const _Efl_Class * kls_itr = NULL ;
const _Efl_Class * * mro_itr = klass - > mro ;
2013-06-17 14:41:02 -07:00
EINA_LIST_FREE ( mro , kls_itr )
{
* ( mro_itr + + ) = kls_itr ;
DBG ( " Added '%s' to MRO " , kls_itr - > desc - > name ) ;
}
* ( mro_itr ) = NULL ;
}
2014-03-05 13:44:21 -08:00
size_t extn_data_off = klass - > data_offset ;
2016-08-15 06:44:41 -07:00
if ( klass - > desc - > type ! = EFL_CLASS_TYPE_MIXIN )
2014-03-05 13:44:21 -08:00
extn_data_off + = EO_ALIGN_SIZE ( klass - > desc - > data_size ) ;
2013-06-17 14:32:50 -07:00
2013-06-17 14:48:22 -07:00
/* Feed the mixins data offsets and free the mixins list. */
2012-04-19 01:52:25 -07:00
{
2016-08-09 06:10:05 -07:00
const _Efl_Class * kls_itr = NULL ;
2013-06-17 14:48:22 -07:00
Eo_Extension_Data_Offset * extn_data_itr = klass - > extn_data_off ;
2013-06-17 14:47:15 -07:00
EINA_LIST_FREE ( mixins , kls_itr )
2012-04-19 01:52:25 -07:00
{
2013-06-17 14:47:15 -07:00
extn_data_itr - > klass = kls_itr ;
extn_data_itr - > offset = extn_data_off ;
2012-04-19 01:52:25 -07:00
2013-06-17 14:47:15 -07:00
extn_data_off + = EO_ALIGN_SIZE ( extn_data_itr - > klass - > desc - > data_size ) ;
extn_data_itr + + ;
2012-04-19 01:52:25 -07:00
2013-06-17 14:47:15 -07:00
DBG ( " Added '%s' to Data Offset info " , kls_itr - > desc - > name ) ;
}
extn_data_itr - > klass = 0 ;
extn_data_itr - > offset = 0 ;
2012-04-19 01:52:25 -07:00
}
2015-10-12 08:12:36 -07:00
klass - > obj_size = extn_data_off ;
2013-06-17 15:08:58 -07:00
if ( getenv ( " EO_DEBUG " ) )
2012-04-12 05:25:29 -07:00
{
2013-06-17 15:08:58 -07:00
fprintf ( stderr , " Eo class '%s' will take %u bytes per object. \n " ,
desc - > name , klass - > obj_size ) ;
2012-04-12 05:25:29 -07:00
}
2012-04-23 01:10:04 -07:00
2012-07-10 07:01:45 -07:00
_eo_class_base_op_init ( klass ) ;
2014-01-09 05:42:17 -08:00
2012-05-07 23:56:57 -07:00
/* Flatten the function array */
{
2016-08-09 06:10:05 -07:00
const _Efl_Class * * mro_itr = klass - > mro ;
2012-05-07 23:56:57 -07:00
for ( ; * mro_itr ; mro_itr + + )
;
2012-05-21 08:18:52 -07:00
/* Skip ourselves. */
for ( mro_itr - - ; mro_itr > klass - > mro ; mro_itr - - )
2012-05-07 23:56:57 -07:00
{
2016-05-18 10:12:39 -07:00
_vtable_copy_all ( & klass - > vtable , & ( * mro_itr ) - > vtable ) ;
2012-05-07 23:56:57 -07:00
}
}
2012-06-13 04:39:12 -07:00
/* Mark which classes we implement */
{
2016-08-09 06:10:05 -07:00
const _Efl_Class * * extn_itr ;
2012-06-13 04:39:12 -07:00
for ( extn_itr = klass - > extensions ; * extn_itr ; extn_itr + + )
{
2016-08-09 06:10:05 -07:00
const _Efl_Class * extn = * extn_itr ;
2012-06-13 04:39:12 -07:00
/* Set it in the dich. */
2016-05-19 03:33:17 -07:00
_vtable_func_set ( & klass - > vtable , klass , extn - > base_id +
2012-07-10 07:01:45 -07:00
extn - > desc - > ops . count , _eo_class_isa_func ) ;
2012-06-13 04:39:12 -07:00
}
2016-05-19 03:33:17 -07:00
_vtable_func_set ( & klass - > vtable , klass , klass - > base_id + klass - > desc - > ops . count ,
2012-07-10 07:01:45 -07:00
_eo_class_isa_func ) ;
2012-06-13 04:39:12 -07:00
if ( klass - > parent )
{
2016-05-19 03:33:17 -07:00
_vtable_func_set ( & klass - > vtable , klass ,
2012-07-10 07:01:45 -07:00
klass - > parent - > base_id + klass - > parent - > desc - > ops . count ,
_eo_class_isa_func ) ;
2012-06-13 04:39:12 -07:00
}
}
2016-05-19 03:33:17 -07:00
if ( ! _eo_class_funcs_set ( & klass - > vtable , & ( klass - > desc - > ops ) , klass , klass , EINA_FALSE ) )
2014-01-09 05:42:17 -08:00
{
2014-04-01 08:21:13 -07:00
eina_spinlock_free ( & klass - > objects . trash_lock ) ;
eina_spinlock_free ( & klass - > iterators . trash_lock ) ;
2016-05-19 03:33:17 -07:00
_vtable_func_clean_all ( & klass - > vtable ) ;
2014-04-01 08:21:13 -07:00
free ( klass ) ;
2014-05-01 05:28:16 -07:00
return NULL ;
2014-01-09 05:42:17 -08:00
}
2013-03-12 03:16:43 -07:00
{
2016-04-23 20:00:37 -07:00
Eo_Id new_id ;
2013-06-17 15:08:58 -07:00
2016-08-15 06:44:41 -07:00
eina_spinlock_take ( & _efl_class_creation_lock ) ;
2016-04-23 20:00:37 -07:00
new_id = ( _eo_classes_last_id + 1 ) | MASK_CLASS_TAG ;
_eo_classes_expand ( ) ;
2016-01-07 05:00:26 -08:00
_eo_classes [ _UNMASK_ID ( new_id ) - 1 ] = klass ;
2016-08-15 06:44:41 -07:00
eina_spinlock_release ( & _efl_class_creation_lock ) ;
2016-01-07 05:00:26 -08:00
klass - > header . id = new_id ;
2013-03-12 03:16:43 -07:00
}
2013-06-17 15:08:58 -07:00
_eo_class_constructor ( klass ) ;
2012-04-05 08:31:15 -07:00
2014-02-19 01:13:47 -08:00
DBG ( " Finished building class '%s' " , klass - > desc - > name ) ;
2013-04-18 04:19:02 -07:00
return _eo_class_id_get ( klass ) ;
2012-04-05 08:31:15 -07:00
}
2016-05-19 03:33:17 -07:00
EAPI Eina_Bool
2016-08-15 06:44:41 -07:00
efl_object_override ( Eo * eo_id , const Efl_Object_Ops * ops )
2016-05-19 03:33:17 -07:00
{
EO_OBJ_POINTER_RETURN_VAL ( eo_id , obj , EINA_FALSE ) ;
2016-08-09 06:10:05 -07:00
EO_CLASS_POINTER_RETURN_VAL ( EFL_OBJECT_OVERRIDE_CLASS , klass , EINA_FALSE ) ;
2016-05-19 03:33:17 -07:00
Eo_Vtable * previous = obj - > vtable ;
2016-07-18 01:44:51 -07:00
2016-07-19 01:21:36 -07:00
if ( ! ops )
2016-07-18 01:44:51 -07:00
{
if ( obj - > vtable ! = & obj - > klass - > vtable )
{
free ( obj - > vtable ) ;
obj - > vtable = ( Eo_Vtable * ) & obj - > klass - > vtable ;
}
return EINA_TRUE ;
}
if ( obj - > vtable = = & obj - > klass - > vtable )
{
obj - > vtable = calloc ( 1 , sizeof ( * obj - > vtable ) ) ;
_vtable_init ( obj - > vtable , previous - > size ) ;
_vtable_copy_all ( obj - > vtable , previous ) ;
}
2016-07-20 21:42:37 -07:00
else
{
ERR ( " Function table already overridden, not allowed to override again. "
" Call with NULL to reset the function table first. " ) ;
return EINA_FALSE ;
}
2016-05-19 03:33:17 -07:00
2016-07-19 01:21:36 -07:00
if ( ! _eo_class_funcs_set ( obj - > vtable , ops , obj - > klass , klass , EINA_TRUE ) )
2016-05-19 03:33:17 -07:00
{
ERR ( " Failed to override functions for %p " , eo_id ) ;
return EINA_FALSE ;
}
return EINA_TRUE ;
}
2012-06-13 04:39:12 -07:00
EAPI Eina_Bool
2016-08-15 06:44:41 -07:00
efl_isa ( const Eo * eo_id , const Efl_Class * klass_id )
2012-06-13 04:39:12 -07:00
{
2013-12-26 14:46:50 -08:00
EO_OBJ_POINTER_RETURN_VAL ( eo_id , obj , EINA_FALSE ) ;
2013-09-26 08:06:46 -07:00
EO_CLASS_POINTER_RETURN_VAL ( klass_id , klass , EINA_FALSE ) ;
2016-05-18 10:12:39 -07:00
const op_type_funcs * func = _vtable_func_get ( obj - > vtable ,
2012-07-10 07:01:45 -07:00
klass - > base_id + klass - > desc - > ops . count ) ;
2012-06-13 04:39:12 -07:00
/* Currently implemented by reusing the LAST op id. Just marking it with
* _eo_class_isa_func . */
return ( func & & ( func - > func = = _eo_class_isa_func ) ) ;
}
2012-05-01 00:40:14 -07:00
EAPI Eo *
2016-08-15 06:44:41 -07:00
efl_xref_internal ( const char * file , int line , Eo * obj_id , const Eo * ref_obj_id )
2012-04-17 08:22:22 -07:00
{
2016-08-15 06:44:41 -07:00
efl_ref ( obj_id ) ;
2012-04-17 08:22:22 -07:00
2013-01-18 08:57:57 -08:00
# ifdef EO_DEBUG
2016-07-12 02:26:23 -07:00
EO_OBJ_POINTER_RETURN_VAL ( obj_id , obj , obj_id ) ;
2012-05-01 00:40:14 -07:00
Eo_Xref_Node * xref = calloc ( 1 , sizeof ( * xref ) ) ;
2013-04-18 04:19:02 -07:00
xref - > ref_obj = ref_obj_id ;
2012-04-17 08:22:22 -07:00
xref - > file = file ;
xref - > line = line ;
obj - > xrefs = eina_inlist_prepend ( obj - > xrefs , EINA_INLIST_GET ( xref ) ) ;
# else
2013-04-18 04:19:02 -07:00
( void ) ref_obj_id ;
2012-04-17 08:22:22 -07:00
( void ) file ;
( void ) line ;
# endif
2013-04-18 04:19:02 -07:00
return obj_id ;
2012-04-17 08:22:22 -07:00
}
EAPI void
2016-08-15 06:44:41 -07:00
efl_xunref ( Eo * obj_id , const Eo * ref_obj_id )
2012-04-17 08:22:22 -07:00
{
2013-04-18 04:19:02 -07:00
EO_OBJ_POINTER_RETURN ( obj_id , obj ) ;
2013-01-18 08:57:57 -08:00
# ifdef EO_DEBUG
2012-05-01 00:40:14 -07:00
Eo_Xref_Node * xref = NULL ;
2012-04-17 08:22:22 -07:00
EINA_INLIST_FOREACH ( obj - > xrefs , xref )
{
2013-03-19 23:56:15 -07:00
if ( xref - > ref_obj = = ref_obj_id )
2013-04-02 17:31:17 -07:00
break ;
2012-04-17 08:22:22 -07:00
}
if ( xref )
{
obj - > xrefs = eina_inlist_remove ( obj - > xrefs , EINA_INLIST_GET ( xref ) ) ;
free ( xref ) ;
}
else
{
2013-03-19 23:56:15 -07:00
ERR ( " ref_obj (%p) does not reference obj (%p). Aborting unref. " , ref_obj_id , obj_id ) ;
2012-04-17 08:22:22 -07:00
return ;
}
# else
2013-04-18 04:19:02 -07:00
( void ) ref_obj_id ;
2012-04-17 08:22:22 -07:00
# endif
2016-08-15 06:44:41 -07:00
efl_unref ( obj_id ) ;
2012-05-06 05:03:26 -07:00
}
2012-05-01 00:40:14 -07:00
EAPI Eo *
2016-08-15 06:44:41 -07:00
efl_ref ( const Eo * obj_id )
2012-04-05 08:31:15 -07:00
{
2013-04-18 04:19:02 -07:00
EO_OBJ_POINTER_RETURN_VAL ( obj_id , obj , ( Eo * ) obj_id ) ;
2012-04-23 01:10:04 -07:00
2016-07-12 02:26:23 -07:00
+ + ( obj - > user_refcount ) ;
if ( EINA_UNLIKELY ( obj - > user_refcount = = 1 ) )
{
2016-08-15 06:44:41 -07:00
_efl_ref ( obj ) ;
2016-07-12 02:26:23 -07:00
}
2013-04-18 04:19:02 -07:00
return ( Eo * ) obj_id ;
2012-04-05 08:31:15 -07:00
}
2012-05-06 05:03:26 -07:00
EAPI void
2016-08-15 06:44:41 -07:00
efl_unref ( const Eo * obj_id )
2012-05-06 05:03:26 -07:00
{
2013-04-18 04:19:02 -07:00
EO_OBJ_POINTER_RETURN ( obj_id , obj ) ;
2012-05-06 05:03:26 -07:00
2016-07-12 02:26:23 -07:00
- - ( obj - > user_refcount ) ;
if ( EINA_UNLIKELY ( obj - > user_refcount < = 0 ) )
{
if ( obj - > user_refcount < 0 )
{
ERR ( " Obj:%p. User refcount (%d) < 0. Too many unrefs. " , obj , obj - > user_refcount ) ;
return ;
}
2016-08-15 06:44:41 -07:00
_efl_unref ( obj ) ;
2016-07-12 02:26:23 -07:00
}
2012-05-06 05:03:26 -07:00
}
2012-04-11 00:05:37 -07:00
EAPI int
2016-08-15 06:44:41 -07:00
efl_ref_get ( const Eo * obj_id )
2012-04-11 00:05:37 -07:00
{
2013-04-18 04:19:02 -07:00
EO_OBJ_POINTER_RETURN_VAL ( obj_id , obj , 0 ) ;
2012-04-23 01:10:04 -07:00
2016-07-12 02:26:23 -07:00
return obj - > user_refcount ;
2012-04-11 00:05:37 -07:00
}
2016-07-28 08:00:49 -07:00
EAPI int
2016-08-15 06:44:41 -07:00
___efl_ref2_get ( const Eo * obj_id )
2016-07-28 08:00:49 -07:00
{
EO_OBJ_POINTER_RETURN_VAL ( obj_id , obj , 0 ) ;
return obj - > refcount ;
}
EAPI void
2016-08-15 06:44:41 -07:00
___efl_ref2_reset ( const Eo * obj_id )
2016-07-28 08:00:49 -07:00
{
EO_OBJ_POINTER_RETURN ( obj_id , obj ) ;
obj - > refcount = 0 ;
}
2016-03-07 23:57:22 -08:00
EAPI void
2016-08-15 06:44:41 -07:00
efl_del_intercept_set ( Eo * obj_id , Efl_Del_Intercept del_intercept_func )
2016-03-07 23:57:22 -08:00
{
EO_OBJ_POINTER_RETURN ( obj_id , obj ) ;
obj - > del_intercept = del_intercept_func ;
}
2016-08-15 06:44:41 -07:00
EAPI Efl_Del_Intercept
2016-08-09 06:10:05 -07:00
efl_del_intercept_get ( const Eo * obj_id )
2016-03-07 23:57:22 -08:00
{
EO_OBJ_POINTER_RETURN_VAL ( obj_id , obj , NULL ) ;
return obj - > del_intercept ;
}
2012-06-10 07:04:53 -07:00
void
2013-04-18 04:19:02 -07:00
_eo_condtor_done ( Eo * obj_id )
2012-06-10 07:04:53 -07:00
{
2013-04-18 04:19:02 -07:00
EO_OBJ_POINTER_RETURN ( obj_id , obj ) ;
2012-06-10 07:04:58 -07:00
if ( obj - > condtor_done )
{
ERR ( " Object %p is already constructed at this point. " , obj ) ;
return ;
}
2012-06-10 07:04:53 -07:00
obj - > condtor_done = EINA_TRUE ;
}
2015-10-12 08:21:19 -07:00
static inline void *
2016-08-15 06:44:41 -07:00
_efl_data_scope_safe_get ( const _Eo_Object * obj , const _Efl_Class * klass )
2015-10-12 08:21:19 -07:00
{
if ( EINA_LIKELY ( klass - > desc - > data_size > 0 ) )
{
2016-08-15 06:44:41 -07:00
return _efl_data_scope_get ( obj , klass ) ;
2015-10-12 08:21:19 -07:00
}
return NULL ;
}
2012-05-06 05:03:21 -07:00
static inline void *
2016-08-15 06:44:41 -07:00
_efl_data_scope_get ( const _Eo_Object * obj , const _Efl_Class * klass )
2012-04-05 08:31:15 -07:00
{
2016-08-15 06:44:41 -07:00
if ( EINA_LIKELY ( klass - > desc - > type ! = EFL_CLASS_TYPE_MIXIN ) )
2015-10-12 08:12:36 -07:00
return ( ( char * ) obj ) + klass - > data_offset ;
2013-08-09 06:58:55 -07:00
if ( EINA_UNLIKELY ( klass - > desc - > data_size = = 0 ) )
2015-10-14 12:42:19 -07:00
{
return NULL ;
}
2013-08-09 06:58:55 -07:00
else
2012-04-19 01:52:25 -07:00
{
2013-08-09 06:58:55 -07:00
Eo_Extension_Data_Offset * doff_itr = obj - > klass - > extn_data_off ;
2012-04-19 01:52:25 -07:00
2013-08-09 06:58:55 -07:00
if ( ! doff_itr )
return NULL ;
2012-04-19 01:52:25 -07:00
2013-08-09 06:58:55 -07:00
while ( doff_itr - > klass )
2012-04-19 01:52:25 -07:00
{
2013-08-09 06:58:55 -07:00
if ( doff_itr - > klass = = klass )
2015-10-12 08:12:36 -07:00
return ( ( char * ) obj ) + doff_itr - > offset ;
2013-08-09 06:58:55 -07:00
doff_itr + + ;
2012-04-19 01:52:25 -07:00
}
}
2012-05-06 05:03:21 -07:00
return NULL ;
}
2013-03-19 23:56:15 -07:00
static inline void *
2016-08-15 06:44:41 -07:00
_efl_data_xref_internal ( const char * file , int line , _Eo_Object * obj , const _Efl_Class * klass , const _Eo_Object * ref_obj )
2013-03-19 23:56:15 -07:00
{
2013-05-01 11:45:57 -07:00
void * data = NULL ;
2013-03-19 23:56:15 -07:00
if ( klass ! = NULL )
{
2016-08-15 06:44:41 -07:00
data = _efl_data_scope_safe_get ( obj , klass ) ;
2013-03-19 23:56:15 -07:00
if ( data = = NULL ) return NULL ;
}
# ifdef EO_DEBUG
2016-05-18 07:02:09 -07:00
( obj - > datarefcount ) + + ;
2013-03-19 23:56:15 -07:00
Eo_Xref_Node * xref = calloc ( 1 , sizeof ( * xref ) ) ;
2016-05-17 02:29:14 -07:00
xref - > ref_obj = _eo_obj_id_get ( ref_obj ) ;
2013-03-19 23:56:15 -07:00
xref - > file = file ;
xref - > line = line ;
obj - > data_xrefs = eina_inlist_prepend ( obj - > data_xrefs , EINA_INLIST_GET ( xref ) ) ;
# else
( void ) ref_obj ;
( void ) file ;
( void ) line ;
# endif
return data ;
}
static inline void
2016-08-15 06:44:41 -07:00
_efl_data_xunref_internal ( _Eo_Object * obj , void * data , const _Eo_Object * ref_obj )
2013-03-19 23:56:15 -07:00
{
# ifdef EO_DEBUG
2016-08-09 06:10:05 -07:00
const _Efl_Class * klass = obj - > klass ;
2013-09-23 02:07:07 -07:00
Eina_Bool in_range = ( ( ( char * ) data > = ( ( ( char * ) obj ) + _eo_sz ) ) & &
( ( char * ) data < ( ( ( char * ) obj ) + klass - > obj_size ) ) ) ;
2013-03-19 23:56:15 -07:00
if ( ! in_range )
{
2013-09-27 02:59:41 -07:00
ERR ( " Data %p is not in the data range of the object %p (%s). " , data , ( Eo * ) obj - > headr . id , obj - > klass - > desc - > name ) ;
2013-03-19 23:56:15 -07:00
}
# else
2016-05-18 07:02:09 -07:00
( void ) obj ;
2013-03-19 23:56:15 -07:00
( void ) data ;
# endif
2016-05-18 07:02:09 -07:00
# ifdef EO_DEBUG
2013-03-19 23:56:15 -07:00
if ( obj - > datarefcount = = 0 )
{
2016-05-17 02:29:14 -07:00
ERR ( " Data for object %zx (%s) is already not referenced. " , ( size_t ) _eo_obj_id_get ( obj ) , obj - > klass - > desc - > name ) ;
2013-03-19 23:56:15 -07:00
}
else
{
( obj - > datarefcount ) - - ;
}
Eo_Xref_Node * xref = NULL ;
EINA_INLIST_FOREACH ( obj - > data_xrefs , xref )
{
2016-05-17 02:29:14 -07:00
if ( xref - > ref_obj = = _eo_obj_id_get ( ref_obj ) )
2013-03-19 23:56:15 -07:00
break ;
}
if ( xref )
{
obj - > data_xrefs = eina_inlist_remove ( obj - > data_xrefs , EINA_INLIST_GET ( xref ) ) ;
free ( xref ) ;
}
else
{
2016-05-17 02:29:14 -07:00
ERR ( " ref_obj (0x%zx) does not reference data (%p) of obj (0x%zx). " , ( size_t ) _eo_obj_id_get ( ref_obj ) , data , ( size_t ) _eo_obj_id_get ( obj ) ) ;
2013-03-19 23:56:15 -07:00
}
# else
( void ) ref_obj ;
# endif
}
EAPI void *
2016-08-15 06:44:41 -07:00
efl_data_scope_get ( const Eo * obj_id , const Efl_Class * klass_id )
2012-05-06 05:03:21 -07:00
{
void * ret ;
2013-04-18 04:19:02 -07:00
EO_OBJ_POINTER_RETURN_VAL ( obj_id , obj , NULL ) ;
2013-09-26 08:06:46 -07:00
EO_CLASS_POINTER_RETURN_VAL ( klass_id , klass , NULL ) ;
2012-05-06 05:03:21 -07:00
2013-01-18 08:57:57 -08:00
# ifdef EO_DEBUG
2012-06-14 03:29:39 -07:00
if ( ! _eo_class_mro_has ( obj - > klass , klass ) )
2012-05-06 05:03:21 -07:00
{
ERR ( " Tried getting data of class '%s' from object of class '%s', but the former is not a direct inheritance of the latter. " , klass - > desc - > name , obj - > klass - > desc - > name ) ;
return NULL ;
}
# endif
2016-08-15 06:44:41 -07:00
ret = _efl_data_scope_safe_get ( obj , klass ) ;
2012-05-06 05:03:21 -07:00
2013-01-18 08:57:57 -08:00
# ifdef EO_DEBUG
2012-05-06 05:03:21 -07:00
if ( ! ret & & ( klass - > desc - > data_size = = 0 ) )
2012-05-06 05:03:07 -07:00
{
2014-01-08 02:10:48 -08:00
ERR ( " Tried getting data of class '%s', but it has none. " , klass - > desc - > name ) ;
2012-05-06 05:03:07 -07:00
}
2012-05-21 07:48:32 -07:00
# endif
2012-04-19 01:52:25 -07:00
2012-05-06 05:03:21 -07:00
return ret ;
2012-04-05 08:31:15 -07:00
}
2013-03-19 23:56:15 -07:00
EAPI void *
2016-08-15 06:44:41 -07:00
efl_data_xref_internal ( const char * file , int line , const Eo * obj_id , const Efl_Class * klass_id , const Eo * ref_obj_id )
2013-03-19 23:56:15 -07:00
{
void * ret ;
EO_OBJ_POINTER_RETURN_VAL ( obj_id , obj , NULL ) ;
EO_OBJ_POINTER_RETURN_VAL ( ref_obj_id , ref_obj , NULL ) ;
2016-08-09 06:10:05 -07:00
_Efl_Class * klass = NULL ;
2013-03-19 23:56:15 -07:00
if ( klass_id )
{
2013-09-26 08:06:46 -07:00
EO_CLASS_POINTER_RETURN_VAL ( klass_id , klass2 , NULL ) ;
klass = klass2 ;
2013-03-19 23:56:15 -07:00
# ifdef EO_DEBUG
if ( ! _eo_class_mro_has ( obj - > klass , klass ) )
{
ERR ( " Tried getting data of class '%s' from object of class '%s', but the former is not a direct inheritance of the latter. " , klass - > desc - > name , obj - > klass - > desc - > name ) ;
return NULL ;
}
# endif
}
2016-08-15 06:44:41 -07:00
ret = _efl_data_xref_internal ( file , line , obj , klass , ref_obj ) ;
2013-03-19 23:56:15 -07:00
# ifdef EO_DEBUG
if ( klass & & ! ret & & ( klass - > desc - > data_size = = 0 ) )
{
2014-01-08 02:10:48 -08:00
ERR ( " Tried getting data of class '%s', but it has none. " , klass - > desc - > name ) ;
2013-03-19 23:56:15 -07:00
}
# endif
return ret ;
}
EAPI void
2016-08-15 06:44:41 -07:00
efl_data_xunref_internal ( const Eo * obj_id , void * data , const Eo * ref_obj_id )
2013-03-19 23:56:15 -07:00
{
EO_OBJ_POINTER_RETURN ( obj_id , obj ) ;
EO_OBJ_POINTER_RETURN ( ref_obj_id , ref_obj ) ;
2016-08-15 06:44:41 -07:00
_efl_data_xunref_internal ( obj , data , ref_obj ) ;
2013-03-19 23:56:15 -07:00
}
2012-04-05 08:31:15 -07:00
EAPI Eina_Bool
2016-08-15 06:44:41 -07:00
efl_object_init ( void )
2012-04-05 08:31:15 -07:00
{
2012-05-01 00:40:14 -07:00
const char * log_dom = " eo " ;
2016-08-15 06:44:41 -07:00
if ( _efl_object_init_count + + > 0 )
2013-04-02 17:31:17 -07:00
return EINA_TRUE ;
2012-04-05 08:31:15 -07:00
eina_init ( ) ;
2013-09-26 14:31:39 -07:00
_eo_sz = EO_ALIGN_SIZE ( sizeof ( _Eo_Object ) ) ;
2016-08-09 06:10:05 -07:00
_eo_class_sz = EO_ALIGN_SIZE ( sizeof ( _Efl_Class ) ) ;
2013-04-10 19:58:53 -07:00
2012-05-01 00:40:14 -07:00
_eo_classes = NULL ;
2012-08-20 00:56:17 -07:00
_eo_classes_last_id = EO_CLASS_IDS_FIRST - 1 ;
2016-08-15 06:44:41 -07:00
_eo_ops_last_id = EFL_OBJECT_OP_IDS_FIRST ;
2012-05-01 00:40:14 -07:00
_eo_log_dom = eina_log_domain_register ( log_dom , EINA_COLOR_LIGHTBLUE ) ;
if ( _eo_log_dom < 0 )
2012-04-05 08:31:15 -07:00
{
2014-01-08 02:10:48 -08:00
EINA_LOG_ERR ( " Could not register log domain: %s. " , log_dom ) ;
2012-04-05 08:31:15 -07:00
return EINA_FALSE ;
}
2016-08-15 06:44:41 -07:00
if ( ! eina_spinlock_new ( & _efl_class_creation_lock ) )
2012-04-23 01:09:54 -07:00
{
EINA_LOG_ERR ( " Could not init lock. " ) ;
return EINA_FALSE ;
}
2015-09-28 09:18:43 -07:00
if ( ! eina_spinlock_new ( & _ops_storage_lock ) )
{
EINA_LOG_ERR ( " Could not init lock. " ) ;
return EINA_FALSE ;
}
2015-11-09 03:45:04 -08:00
if ( ! eina_spinlock_new ( & _super_class_lock ) )
{
EINA_LOG_ERR ( " Could not init lock. " ) ;
return EINA_FALSE ;
}
2012-05-01 00:40:14 -07:00
eina_magic_string_static_set ( EO_EINA_MAGIC , EO_EINA_MAGIC_STR ) ;
2012-06-05 05:05:06 -07:00
eina_magic_string_static_set ( EO_FREED_EINA_MAGIC ,
2013-04-02 17:31:17 -07:00
EO_FREED_EINA_MAGIC_STR ) ;
2012-05-01 00:40:14 -07:00
eina_magic_string_static_set ( EO_CLASS_EINA_MAGIC ,
2013-04-02 17:31:17 -07:00
EO_CLASS_EINA_MAGIC_STR ) ;
2012-04-23 01:10:04 -07:00
2015-10-09 04:06:09 -07:00
# ifndef _WIN32
2015-09-28 09:18:43 -07:00
_ops_storage = eina_hash_pointer_new ( NULL ) ;
2015-10-09 04:06:09 -07:00
# else
_ops_storage = eina_hash_string_superfast_new ( NULL ) ;
# endif
2015-09-28 09:18:43 -07:00
2013-01-18 08:57:57 -08:00
# ifdef EO_DEBUG
2012-07-10 07:01:54 -07:00
/* Call it just for coverage purposes. Ugly I know, but I like it better than
* casting everywhere else . */
2016-08-16 08:28:33 -07:00
_eo_class_isa_func ( NULL , NULL ) ;
2012-07-10 07:01:54 -07:00
# endif
2016-08-15 06:44:41 -07:00
_efl_add_fallback_init ( ) ;
2016-03-29 06:47:22 -07:00
2013-03-27 05:42:55 -07:00
eina_log_timing ( _eo_log_dom ,
2013-04-02 17:31:17 -07:00
EINA_LOG_STATE_STOP ,
EINA_LOG_STATE_INIT ) ;
2013-03-27 05:42:55 -07:00
2016-08-10 07:23:04 -07:00
/* bootstrap EFL_CLASS_CLASS */
( void ) EFL_CLASS_CLASS ;
2013-10-12 14:51:59 -07:00
2012-04-05 08:31:15 -07:00
return EINA_TRUE ;
}
EAPI Eina_Bool
2016-08-15 06:44:41 -07:00
efl_object_shutdown ( void )
2012-04-05 08:31:15 -07:00
{
2012-05-06 05:03:23 -07:00
size_t i ;
2016-08-09 06:10:05 -07:00
_Efl_Class * * cls_itr = _eo_classes + _eo_classes_last_id - 1 ;
2012-04-05 08:31:15 -07:00
2016-08-15 06:44:41 -07:00
if ( - - _efl_object_init_count > 0 )
2013-04-02 17:31:17 -07:00
return EINA_TRUE ;
2012-04-05 08:31:15 -07:00
2013-03-27 05:42:55 -07:00
eina_log_timing ( _eo_log_dom ,
2013-04-02 17:31:17 -07:00
EINA_LOG_STATE_START ,
EINA_LOG_STATE_SHUTDOWN ) ;
2013-03-27 05:42:55 -07:00
2016-08-15 06:44:41 -07:00
_efl_add_fallback_shutdown ( ) ;
2016-03-29 06:47:22 -07:00
2016-07-05 03:12:23 -07:00
for ( i = 0 ; i < _eo_classes_last_id ; i + + , cls_itr - - )
2012-04-05 08:31:15 -07:00
{
if ( * cls_itr )
2013-04-02 17:31:17 -07:00
eo_class_free ( * cls_itr ) ;
2012-04-05 08:31:15 -07:00
}
2016-08-15 06:44:41 -07:00
eina_spinlock_take ( & _efl_class_creation_lock ) ;
2016-04-23 20:00:37 -07:00
_eo_classes_release ( ) ;
2016-08-15 06:44:41 -07:00
eina_spinlock_release ( & _efl_class_creation_lock ) ;
2012-04-05 08:31:15 -07:00
2015-09-28 09:18:43 -07:00
eina_hash_free ( _ops_storage ) ;
2015-11-09 03:45:04 -08:00
eina_spinlock_free ( & _super_class_lock ) ;
2015-09-28 09:18:43 -07:00
eina_spinlock_free ( & _ops_storage_lock ) ;
2016-08-15 06:44:41 -07:00
eina_spinlock_free ( & _efl_class_creation_lock ) ;
2012-04-23 01:09:54 -07:00
2013-04-18 04:19:02 -07:00
_eo_free_ids_tables ( ) ;
2012-05-01 00:40:14 -07:00
eina_log_domain_unregister ( _eo_log_dom ) ;
_eo_log_dom = - 1 ;
2012-04-05 08:31:15 -07:00
2016-08-15 06:44:41 -07:00
+ + _efl_object_init_generation ;
2016-02-03 08:14:07 -08:00
2012-04-05 08:31:15 -07:00
eina_shutdown ( ) ;
2016-02-03 08:32:50 -08:00
return EINA_FALSE ;
2012-04-05 08:31:15 -07:00
}
2012-09-12 04:31:58 -07:00
EAPI Eina_Bool
2016-08-15 06:44:41 -07:00
efl_destructed_is ( const Eo * obj_id )
2012-09-12 04:31:58 -07:00
{
2013-04-18 04:19:02 -07:00
EO_OBJ_POINTER_RETURN_VAL ( obj_id , obj , EINA_FALSE ) ;
2012-09-12 04:31:58 -07:00
2014-11-18 07:24:39 -08:00
return obj - > destructed ;
2012-09-12 04:31:58 -07:00
}
2012-05-21 04:45:32 -07:00
EAPI void
2016-08-15 06:44:41 -07:00
efl_manual_free_set ( Eo * obj_id , Eina_Bool manual_free )
2012-05-21 04:45:32 -07:00
{
2013-04-18 04:19:02 -07:00
EO_OBJ_POINTER_RETURN ( obj_id , obj ) ;
2012-05-21 04:45:32 -07:00
obj - > manual_free = manual_free ;
}
2013-11-26 04:10:53 -08:00
EAPI Eina_Bool
2016-08-15 06:44:41 -07:00
efl_manual_free ( Eo * obj_id )
2012-05-21 04:45:32 -07:00
{
2013-11-26 05:08:55 -08:00
EO_OBJ_POINTER_RETURN_VAL ( obj_id , obj , EINA_FALSE ) ;
2012-05-21 04:45:32 -07:00
if ( EINA_FALSE = = obj - > manual_free )
{
2016-08-15 06:44:41 -07:00
ERR ( " Tried to manually free the object %p while the option has not been set; see efl_manual_free_set for more information. " , obj ) ;
2013-11-26 04:10:53 -08:00
return EINA_FALSE ;
2012-05-21 04:45:32 -07:00
}
2014-11-18 07:24:39 -08:00
if ( ! obj - > destructed )
2012-05-21 04:45:32 -07:00
{
2013-04-18 04:19:02 -07:00
ERR ( " Tried deleting the object %p while still referenced(%d). " , obj_id , obj - > refcount ) ;
2013-11-26 04:10:53 -08:00
return EINA_FALSE ;
2012-05-21 04:45:32 -07:00
}
_eo_free ( obj ) ;
2013-11-26 04:10:53 -08:00
return EINA_TRUE ;
2012-05-21 04:45:32 -07:00
}