2012-09-04 00:03:02 -07:00
# ifdef HAVE_CONFIG_H
# include <config.h>
# endif
2014-05-07 15:15:30 -07:00
# ifdef HAVE_DLADDR
# include <dlfcn.h>
# endif
2012-04-05 08:31:15 -07:00
# include <Eina.h>
2015-05-08 06:21:23 -07:00
# define EO_BASE_BETA
2015-05-01 04:57:40 -07:00
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"
2012-04-05 08:31:15 -07:00
2012-08-20 00:56:17 -07:00
# define EO_CLASS_IDS_FIRST 1
2012-07-10 07:01:45 -07:00
# define EO_OP_IDS_FIRST 1
2012-04-16 05:36:42 -07:00
2012-05-01 00:40:14 -07:00
/* Used inside the class_get functions of classes, see #EO_DEFINE_CLASS */
2013-10-10 01:26:02 -07:00
EAPI Eina_Spinlock _eo_class_creation_lock ;
2012-05-01 00:40:14 -07:00
int _eo_log_dom = - 1 ;
2012-04-05 08:31:15 -07:00
2013-04-18 04:19:02 -07:00
static _Eo_Class * * _eo_classes ;
2013-09-27 02:50:06 -07:00
static Eo_Id _eo_classes_last_id ;
2015-01-12 05:43:25 -08:00
static int _eo_init_count = 0 ;
2012-07-10 07:01:45 -07:00
static Eo_Op _eo_ops_last_id = 0 ;
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 ) ;
static inline void * _eo_data_scope_get ( const _Eo_Object * obj , const _Eo_Class * klass ) ;
static inline void * _eo_data_xref_internal ( const char * file , int line , _Eo_Object * obj , const _Eo_Class * klass , const _Eo_Object * ref_obj ) ;
static inline void _eo_data_xunref_internal ( _Eo_Object * obj , void * data , const _Eo_Object * ref_obj ) ;
2013-04-18 04:19:02 -07:00
static const _Eo_Class * _eo_op_class_get ( Eo_Op op ) ;
2014-04-01 08:21:13 -07:00
static const char * _eo_op_id_name_get ( Eo_Op op ) ;
2012-04-05 08:31:15 -07:00
/* Start of Dich */
2012-07-10 07:01:54 -07:00
/* How we search and store the implementations in classes. */
2012-07-10 07:01:45 -07:00
# define DICH_CHAIN_LAST_BITS 5
# define DICH_CHAIN_LAST_SIZE (1 << DICH_CHAIN_LAST_BITS)
2013-08-09 06:58:55 -07:00
# define DICH_CHAIN1(x) ((x) >> DICH_CHAIN_LAST_BITS)
# define DICH_CHAIN_LAST(x) ((x) & ((1 << DICH_CHAIN_LAST_BITS) - 1))
2012-04-05 08:31:15 -07:00
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) ({ \
2014-03-11 08:50:44 -07:00
( _Eo_Class * ) ( ( ( _UNMASK_ID ( id ) < = _eo_classes_last_id ) & & ( _UNMASK_ID ( id ) > 0 ) ) ? \
( _eo_classes [ _UNMASK_ID ( id ) - 1 ] ) : NULL ) ; \
2012-05-06 05:03:23 -07:00
} )
2012-05-07 23:56:57 -07:00
static inline void
2012-07-10 07:01:45 -07:00
_dich_chain_alloc ( Dich_Chain1 * chain1 )
2012-05-07 23:56:57 -07:00
{
if ( ! chain1 - > funcs )
{
2012-07-10 07:01:45 -07:00
chain1 - > funcs = calloc ( DICH_CHAIN_LAST_SIZE , sizeof ( * ( chain1 - > funcs ) ) ) ;
2012-05-07 23:56:57 -07:00
}
}
static inline void
2013-04-18 04:19:02 -07:00
_dich_copy_all ( _Eo_Class * dst , const _Eo_Class * src )
2012-05-07 23:56:57 -07:00
{
2012-07-15 00:56:02 -07:00
Eo_Op i ;
2012-05-07 23:56:57 -07:00
const Dich_Chain1 * sc1 = src - > chain ;
Dich_Chain1 * dc1 = dst - > chain ;
2012-07-15 05:27:56 -07:00
for ( i = 0 ; i < src - > chain_size ; i + + , sc1 + + , dc1 + + )
2012-05-07 23:56:57 -07:00
{
if ( sc1 - > funcs )
{
size_t j ;
2012-05-14 08:20:46 -07:00
2012-07-10 07:01:45 -07:00
_dich_chain_alloc ( dc1 ) ;
2012-05-07 23:56:57 -07:00
const op_type_funcs * sf = sc1 - > funcs ;
op_type_funcs * df = dc1 - > funcs ;
2012-07-10 07:01:45 -07:00
for ( j = 0 ; j < DICH_CHAIN_LAST_SIZE ; j + + , df + + , sf + + )
2012-05-07 23:56:57 -07:00
{
if ( sf - > func )
{
memcpy ( df , sf , sizeof ( * df ) ) ;
}
}
}
}
}
static inline const op_type_funcs *
2013-04-18 04:19:02 -07:00
_dich_func_get ( const _Eo_Class * klass , Eo_Op op )
2012-04-05 08:31:15 -07:00
{
2012-07-10 07:01:45 -07:00
size_t idx1 = DICH_CHAIN1 ( op ) ;
if ( EINA_UNLIKELY ( idx1 > = klass - > chain_size ) )
2012-04-05 08:31:15 -07:00
return NULL ;
2012-07-10 07:01:45 -07:00
Dich_Chain1 * chain1 = & klass - > chain [ idx1 ] ;
if ( EINA_UNLIKELY ( ! chain1 - > funcs ) )
return NULL ;
return & chain1 - > funcs [ DICH_CHAIN_LAST ( op ) ] ;
2012-04-05 08:31:15 -07:00
}
2014-01-09 05:43:26 -08:00
static inline Eina_Bool
2013-04-18 04:19:02 -07:00
_dich_func_set ( _Eo_Class * klass , Eo_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 ) ;
2012-05-06 05:03:23 -07:00
Dich_Chain1 * chain1 = & klass - > chain [ idx1 ] ;
2012-07-10 07:01:45 -07:00
_dich_chain_alloc ( chain1 ) ;
2014-01-03 07:02:00 -08:00
fsrc = & chain1 - > funcs [ DICH_CHAIN_LAST ( op ) ] ;
if ( fsrc - > src = = klass )
2012-07-26 05:21:01 -07:00
{
2013-04-18 04:19:02 -07:00
const _Eo_Class * op_kls = _eo_op_class_get ( op ) ;
2014-04-01 08:21:13 -07:00
const char * op_name = _eo_op_id_name_get ( op ) ;
2014-01-09 05:43:26 -08:00
ERR ( " Class '%s': Overriding func %p for op %d (%s:'%s') with %p. " ,
klass - > desc - > name , fsrc - > func , op , op_kls - > desc - > name , op_name , func ) ;
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
}
static inline void
2013-04-18 04:19:02 -07:00
_dich_func_clean_all ( _Eo_Class * klass )
2012-04-05 08:31:15 -07:00
{
2012-05-06 05:03:23 -07:00
size_t i ;
2012-04-05 08:31:15 -07:00
Dich_Chain1 * chain1 = klass - > chain ;
2012-07-15 05:27:56 -07:00
for ( i = 0 ; i < klass - > chain_size ; i + + , chain1 + + )
2012-05-06 05:03:23 -07:00
{
if ( chain1 - > funcs )
free ( chain1 - > funcs ) ;
2012-04-05 08:31:15 -07:00
}
2012-05-06 05:03:23 -07:00
free ( klass - > chain ) ;
klass - > chain = NULL ;
2012-04-05 08:31:15 -07:00
}
/* END OF DICH */
2013-09-26 14:32:43 -07:00
static inline Eina_Bool
2013-12-26 14:46:50 -08:00
_eo_is_a_class ( const Eo * eo_id )
2013-09-26 14:32:43 -07:00
{
2013-09-27 03:13:14 -07:00
Eo_Id oid ;
2013-09-26 14:32:43 -07:00
# ifdef HAVE_EO_ID
2013-12-26 14:46:50 -08:00
oid = ( Eo_Id ) eo_id ;
2013-09-26 14:32:43 -07:00
# else
2013-12-26 14:46:50 -08:00
/* fortunately EO_OBJ_POINTER_RETURN* will handle NULL eo_id */
if ( ! eo_id ) return EINA_FALSE ;
2015-05-28 08:49:13 -07:00
oid = ( ( Eo_Header * ) eo_id ) - > id ;
2013-09-26 14:32:43 -07:00
# endif
2014-04-14 02:34:57 -07:00
return ( ( ( ( oid > > REF_TAG_SHIFT ) & 0x1 ) = = 0x0 ) & &
( oid & MASK_CLASS_TAG ) ) ;
2013-09-26 14:32:43 -07:00
}
2013-04-18 04:19:02 -07:00
static inline _Eo_Class *
2013-09-27 08:38:15 -07:00
_eo_class_pointer_get ( const Eo_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
2013-09-27 03:13:14 -07:00
return ( _Eo_Class * ) klass_id ;
2013-04-18 04:19:02 -07:00
# endif
}
static const _Eo_Class *
2012-07-10 07:01:45 -07:00
_eo_op_class_get ( Eo_Op op )
{
/* FIXME: Make it fast. */
2013-04-18 04:19:02 -07:00
_Eo_Class * * itr = _eo_classes ;
2012-09-03 00:26:57 -07:00
int mid , max , min ;
min = 0 ;
max = _eo_classes_last_id - 1 ;
while ( min < = max )
2012-07-10 07:01:45 -07:00
{
2012-09-03 00:26:57 -07:00
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 ] ;
2012-07-10 07:01:45 -07:00
}
2012-09-03 00:26:57 -07:00
return NULL ;
2012-07-10 07:01:45 -07:00
}
2014-04-02 01:46:34 -07:00
static const Eo_Op_Description *
_eo_op_id_desc_get ( Eo_Op op )
2014-01-03 07:00:24 -08:00
{
unsigned int i ;
const _Eo_Class * klass ;
2014-04-02 01:46:34 -07:00
const Eo_Op_Description * op_descs ;
2014-01-03 07:00:24 -08:00
if ( op = = EO_NOOP )
return NULL ;
klass = _eo_op_class_get ( op ) ;
if ( klass )
{
2014-04-17 12:10:34 -07:00
DBG ( " klass %p %s " , klass , klass - > desc - > name ) ;
2014-05-07 07:05:26 -07:00
op_descs = klass - > desc - > ops . descs ;
2014-01-03 07:00:24 -08:00
for ( i = 0 ; i < klass - > desc - > ops . count ; i + + )
{
if ( op_descs [ i ] . op = = op )
return & op_descs [ i ] ;
}
}
return NULL ;
}
2015-09-28 06:15:15 -07:00
static const char *
_eo_op_desc_name_get ( const Eo_Op_Description * desc )
{
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 ;
}
2012-04-18 00:58:34 -07:00
static const char *
2014-04-01 08:21:13 -07:00
_eo_op_id_name_get ( Eo_Op op )
2012-04-18 00:58:34 -07:00
{
2014-04-02 01:46:34 -07:00
const Eo_Op_Description * desc = _eo_op_id_desc_get ( op ) ;
2015-09-28 06:15:15 -07:00
return _eo_op_desc_name_get ( desc ) ;
2012-04-18 00:58:34 -07:00
}
2013-11-11 05:06:51 -08:00
static inline const op_type_funcs *
2014-04-02 01:46:34 -07:00
_eo_kls_itr_next ( const _Eo_Class * orig_kls , const _Eo_Class * cur_klass , Eo_Op op )
2012-04-11 00:05:30 -07:00
{
2013-04-18 04:19:02 -07:00
const _Eo_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
{
const op_type_funcs * fsrc = _dich_func_get ( * kls_itr , 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
2014-04-02 01:46:34 -07:00
EAPI Eo_Hook_Call eo_hook_call_pre = NULL ;
EAPI Eo_Hook_Call eo_hook_call_post = NULL ;
2013-08-01 02:49:27 -07:00
2014-04-02 01:46:34 -07:00
# define EO_INVALID_DATA (void *) -1
2014-09-23 01:51:05 -07:00
// 1024 entries == 16k or 32k (32 or 64bit) for eo call stack. that's 1023
// imbricated/recursive calls it can handle before barfing. i'd say that's ok
# define EO_CALL_STACK_DEPTH_MIN 1024
# define EO_CALL_STACK_SHRINK_DROP (EO_CALL_STACK_DEPTH_MIN >> 1)
2013-10-02 05:57:45 -07:00
2014-04-02 01:46:34 -07:00
typedef struct _Eo_Stack_Frame
2013-12-25 06:16:34 -08:00
{
2013-10-02 02:47:10 -07:00
const Eo * eo_id ;
2013-11-11 02:34:35 -08:00
union {
_Eo_Object * obj ;
const _Eo_Class * kls ;
} o ;
2013-10-02 01:44:33 -07:00
const _Eo_Class * cur_klass ;
2013-07-24 15:10:26 -07:00
void * obj_data ;
2014-04-02 01:46:34 -07:00
} Eo_Stack_Frame ;
2013-12-25 06:16:34 -08:00
2014-09-23 01:43:36 -07:00
# define EO_CALL_STACK_SIZE (EO_CALL_STACK_DEPTH_MIN * sizeof(Eo_Stack_Frame))
2014-04-02 01:46:34 -07:00
static Eina_TLS _eo_call_stack_key = 0 ;
2014-01-22 02:18:31 -08:00
2014-04-02 01:46:34 -07:00
typedef struct _Eo_Call_Stack {
2014-04-22 04:22:35 -07:00
Eo_Stack_Frame * frames ;
Eo_Stack_Frame * frame_ptr ;
Eo_Stack_Frame * last_frame ;
Eo_Stack_Frame * shrink_frame ;
2014-04-02 01:46:34 -07:00
} Eo_Call_Stack ;
2013-12-25 06:16:34 -08:00
2014-04-22 03:17:26 -07:00
# define MEM_PAGE_SIZE 4096
static void *
2014-09-23 01:43:36 -07:00
_eo_call_stack_mem_alloc ( size_t size )
2014-04-22 03:17:26 -07:00
{
2014-08-21 03:53:41 -07:00
# ifdef HAVE_MMAP
2014-04-22 03:17:26 -07:00
// allocate eo call stack via mmped anon segment if on linux - more
// secure and safe. also gives page aligned memory allowing madvise
void * ptr ;
size_t newsize ;
2014-09-23 01:43:36 -07:00
newsize = MEM_PAGE_SIZE * ( ( size + MEM_PAGE_SIZE - 1 ) /
2014-04-22 03:17:26 -07:00
MEM_PAGE_SIZE ) ;
ptr = mmap ( NULL , newsize , PROT_READ | PROT_WRITE ,
2014-09-03 08:14:39 -07:00
MAP_PRIVATE | MAP_ANON , - 1 , 0 ) ;
2014-04-22 03:17:26 -07:00
if ( ptr = = MAP_FAILED )
{
2014-09-23 01:29:44 -07:00
ERR ( " eo call stack mmap failed. " ) ;
2014-04-22 03:17:26 -07:00
return NULL ;
}
return ptr ;
# else
//in regular cases just use malloc
2014-09-23 01:43:36 -07:00
return calloc ( 1 , size ) ;
2014-08-21 02:27:14 -07:00
# endif
2014-04-22 03:17:26 -07:00
}
2014-08-21 03:53:41 -07:00
# ifdef HAVE_MMAP
2014-04-22 03:17:26 -07:00
static void
2014-09-23 01:43:36 -07:00
_eo_call_stack_mem_resize ( void * * ptr EINA_UNUSED , size_t newsize , size_t size )
2014-04-22 03:17:26 -07:00
{
2014-09-23 01:47:24 -07:00
// FIXME we don't grow
2014-09-23 01:43:36 -07:00
if ( newsize > size )
2014-04-22 03:17:26 -07:00
{
2014-09-23 01:29:44 -07:00
CRI ( " eo call stack overflow, abort. " ) ;
2014-04-22 03:17:26 -07:00
abort ( ) ;
}
2014-09-23 01:47:24 -07:00
// FIXME resize call stack down
return ;
2014-04-22 03:17:26 -07:00
size_t addr = MEM_PAGE_SIZE * ( ( newsize + MEM_PAGE_SIZE - 1 ) /
MEM_PAGE_SIZE ) ;
2014-09-23 01:43:36 -07:00
madvise ( ( ( unsigned char * ) * ptr ) + addr , size - addr , MADV_DONTNEED ) ;
2014-04-22 03:17:26 -07:00
# else
2014-05-30 01:38:27 -07:00
static void
2014-09-23 01:47:24 -07:00
_eo_call_stack_mem_resize ( void * * ptr , size_t newsize , size_t size EINA_UNUSED )
2014-05-30 01:38:27 -07:00
{
2014-09-23 01:47:24 -07:00
* ptr = realloc ( * ptr , newsize ) ;
if ( ! * ptr )
{
CRI ( " eo call stack resize failed, abort. " ) ;
abort ( ) ;
}
2014-04-22 03:17:26 -07:00
# endif
}
2014-08-21 03:53:41 -07:00
# ifdef HAVE_MMAP
2014-04-22 03:17:26 -07:00
static void
2014-09-23 01:43:36 -07:00
_eo_call_stack_mem_free ( void * ptr , size_t size )
2014-04-22 03:17:26 -07:00
{
// free mmaped memory
2014-09-23 01:43:36 -07:00
munmap ( ptr , size ) ;
2014-04-22 03:17:26 -07:00
# else
2014-05-30 01:38:27 -07:00
static void
2014-09-23 01:43:36 -07:00
_eo_call_stack_mem_free ( void * ptr , size_t size EINA_UNUSED )
2014-05-30 01:38:27 -07:00
{
2014-04-22 03:17:26 -07:00
// free regular memory
free ( ptr ) ;
# endif
}
2014-04-02 01:46:34 -07:00
static Eo_Call_Stack *
_eo_call_stack_create ( )
2013-10-02 05:57:45 -07:00
{
2014-04-02 01:46:34 -07:00
Eo_Call_Stack * stack ;
2014-01-22 02:18:31 -08:00
2014-04-02 01:46:34 -07:00
stack = calloc ( 1 , sizeof ( Eo_Call_Stack ) ) ;
2014-01-22 02:18:31 -08:00
if ( ! stack )
return NULL ;
2014-09-23 01:43:36 -07:00
stack - > frames = _eo_call_stack_mem_alloc ( EO_CALL_STACK_SIZE ) ;
2014-01-22 02:18:31 -08:00
if ( ! stack - > frames )
{
free ( stack ) ;
return NULL ;
}
2013-10-02 05:57:45 -07:00
// first frame is never used
2014-01-22 02:18:31 -08:00
stack - > frame_ptr = stack - > frames ;
2014-09-23 01:24:06 -07:00
stack - > last_frame = & stack - > frames [ EO_CALL_STACK_DEPTH_MIN - 1 ] ;
2014-01-22 02:18:31 -08:00
stack - > shrink_frame = stack - > frames ;
2013-10-02 05:57:45 -07:00
2014-01-22 02:18:31 -08:00
return stack ;
2013-10-02 05:57:45 -07:00
}
static void
2014-04-02 01:46:34 -07:00
_eo_call_stack_free ( void * ptr )
2013-10-02 05:57:45 -07:00
{
2014-04-02 01:46:34 -07:00
Eo_Call_Stack * stack = ( Eo_Call_Stack * ) ptr ;
2014-01-22 02:18:31 -08:00
if ( ! stack ) return ;
if ( stack - > frames )
2014-09-23 01:43:36 -07:00
_eo_call_stack_mem_free ( stack - > frames , EO_CALL_STACK_SIZE ) ;
2014-09-23 01:41:13 -07:00
2014-01-22 02:18:31 -08:00
free ( stack ) ;
2013-10-02 05:57:45 -07:00
}
2013-12-25 06:16:34 -08:00
2014-04-02 01:46:34 -07:00
static inline Eo_Call_Stack *
2014-08-01 03:21:40 -07:00
_eo_call_stack_get ( Eina_Bool is_main_loop )
2014-01-22 02:18:31 -08:00
{
2014-08-01 03:21:40 -07:00
static Eo_Call_Stack * main_loop_stack = NULL ;
Eo_Call_Stack * stack = is_main_loop ?
main_loop_stack : eina_tls_get ( _eo_call_stack_key ) ;
2014-01-22 02:18:31 -08:00
if ( stack ) return stack ;
2014-04-02 01:46:34 -07:00
stack = _eo_call_stack_create ( ) ;
2014-01-22 02:18:31 -08:00
if ( ! stack )
{
2014-04-02 01:46:34 -07:00
EINA_LOG_ERR ( " Could not alloc eo call stack. " ) ;
2014-01-22 02:18:31 -08:00
return NULL ;
}
2014-08-01 03:21:40 -07:00
if ( is_main_loop )
{
main_loop_stack = stack ;
}
else if ( ! eina_tls_set ( _eo_call_stack_key , stack ) )
2014-01-22 02:18:31 -08:00
{
2014-04-02 01:46:34 -07:00
EINA_LOG_ERR ( " Could not set eo call stack in TLS key. " ) ;
_eo_call_stack_free ( stack ) ;
2014-01-22 02:18:31 -08:00
return NULL ;
}
return stack ;
}
2013-12-30 06:24:15 -08:00
static inline void
2014-04-02 01:46:34 -07:00
_eo_call_stack_resize ( Eo_Call_Stack * stack , Eina_Bool grow )
2013-12-30 06:24:15 -08:00
{
size_t sz , next_sz ;
int frame_offset ;
2014-01-22 02:18:31 -08:00
sz = stack - > last_frame - stack - > frames + 1 ;
2013-12-30 06:24:15 -08:00
if ( grow )
2014-09-23 01:26:33 -07:00
next_sz = sz * 2 ;
2013-12-30 06:24:15 -08:00
else
2014-09-23 01:26:33 -07:00
next_sz = sz / 2 ;
2014-04-22 04:22:35 -07:00
frame_offset = stack - > frame_ptr - stack - > frames ;
2013-12-30 06:24:15 -08:00
2014-04-10 01:42:54 -07:00
DBG ( " resize from %lu to %lu " , ( long unsigned int ) sz , ( long unsigned int ) next_sz ) ;
2014-09-23 01:47:24 -07:00
_eo_call_stack_mem_resize ( ( void * * ) & ( stack - > frames ) ,
next_sz * sizeof ( Eo_Stack_Frame ) ,
sz * sizeof ( Eo_Stack_Frame ) ) ;
2014-04-17 00:35:43 -07:00
if ( ! stack - > frames )
2013-12-30 06:24:15 -08:00
{
CRI ( " unable to resize call stack, abort. " ) ;
abort ( ) ;
}
2014-01-22 02:18:31 -08:00
stack - > frame_ptr = & stack - > frames [ frame_offset ] ;
stack - > last_frame = & stack - > frames [ next_sz - 1 ] ;
2013-12-30 06:24:15 -08:00
2014-09-23 01:24:06 -07:00
if ( next_sz = = EO_CALL_STACK_DEPTH_MIN )
2013-12-30 06:24:15 -08:00
frame_offset = 0 ;
else
2014-09-23 01:24:06 -07:00
{
if ( grow )
frame_offset = sz - EO_CALL_STACK_SHRINK_DROP ;
else
frame_offset = ( next_sz / 2 ) - EO_CALL_STACK_SHRINK_DROP ;
}
2014-01-22 02:18:31 -08:00
stack - > shrink_frame = & stack - > frames [ frame_offset ] ;
2013-12-30 06:24:15 -08:00
}
2013-10-02 02:47:10 -07:00
static inline Eina_Bool
2014-04-02 01:46:34 -07:00
_eo_do_internal ( const Eo * eo_id , const Eo_Class * cur_klass_id ,
2014-04-17 00:35:43 -07:00
Eina_Bool is_super , Eo_Stack_Frame * fptr , Eo_Stack_Frame * pfptr )
2013-07-08 08:31:36 -07:00
{
2013-12-30 08:53:54 -08:00
Eina_Bool is_klass = _eo_is_a_class ( eo_id ) ;
2013-11-11 02:34:35 -08:00
/* If we are already in the same object context, we inherit info from it. */
2013-10-02 05:57:45 -07:00
if ( pfptr )
2013-10-02 01:44:33 -07:00
{
2014-04-02 01:46:34 -07:00
memcpy ( fptr , pfptr , sizeof ( Eo_Stack_Frame ) ) ;
2013-12-30 08:53:54 -08:00
if ( ! is_klass )
_eo_ref ( fptr - > o . obj ) ;
2013-07-24 15:10:26 -07:00
}
2013-12-25 06:16:34 -08:00
else
2013-07-24 15:10:26 -07:00
{
2013-10-02 05:57:45 -07:00
fptr - > eo_id = eo_id ;
2014-04-02 01:46:34 -07:00
fptr - > obj_data = EO_INVALID_DATA ;
2013-12-30 08:53:54 -08:00
if ( is_klass )
{
EO_CLASS_POINTER_RETURN_VAL ( eo_id , _klass , EINA_FALSE ) ;
fptr - > o . kls = _klass ;
}
else
{
EO_OBJ_POINTER_RETURN_VAL ( eo_id , _obj , EINA_FALSE ) ;
fptr - > o . obj = _obj ;
_eo_ref ( _obj ) ;
}
2013-07-24 15:10:26 -07:00
}
2013-12-25 06:16:34 -08:00
2013-11-11 02:47:13 -08:00
if ( is_super )
2013-10-02 01:44:33 -07:00
{
EO_CLASS_POINTER_RETURN_VAL ( cur_klass_id , cur_klass , EINA_FALSE ) ;
2013-11-11 02:34:35 -08:00
if ( fptr - > cur_klass = = cur_klass )
2014-04-02 01:46:34 -07:00
fptr - > obj_data = EO_INVALID_DATA ;
2013-11-11 02:34:35 -08:00
fptr - > cur_klass = cur_klass ;
2013-10-02 01:44:33 -07:00
}
else
2013-10-02 02:47:10 -07:00
{
2013-11-11 02:34:35 -08:00
fptr - > cur_klass = NULL ;
2013-07-30 06:02:35 -07:00
}
2013-10-02 02:47:10 -07:00
return EINA_TRUE ;
}
EAPI Eina_Bool
2014-09-23 06:36:18 -07:00
_eo_do_start ( const Eo * eo_id , const Eo_Class * cur_klass_id , Eina_Bool is_super , const char * file EINA_UNUSED , const char * func EINA_UNUSED , int line EINA_UNUSED )
2013-10-02 02:47:10 -07:00
{
2014-09-23 06:36:18 -07:00
Eina_Bool is_main_loop = eina_main_loop_is ( ) ;
2014-04-14 02:36:09 -07:00
Eina_Bool ret = EINA_TRUE ;
2014-04-02 01:46:34 -07:00
Eo_Stack_Frame * fptr , * pfptr ;
2014-08-01 03:21:40 -07:00
Eo_Call_Stack * stack = _eo_call_stack_get ( is_main_loop ) ;
2013-12-25 06:16:34 -08:00
2014-01-22 02:18:31 -08:00
if ( stack - > frame_ptr = = stack - > last_frame )
2014-04-02 01:46:34 -07:00
_eo_call_stack_resize ( stack , EINA_TRUE ) ;
2013-12-30 06:24:15 -08:00
2014-01-22 02:18:31 -08:00
fptr = stack - > frame_ptr ;
2013-12-25 06:16:34 -08:00
2013-11-08 04:18:05 -08:00
pfptr = ( ( eo_id ) & & ( fptr - > eo_id = = eo_id ) ? fptr : NULL ) ;
2013-11-11 02:34:35 -08:00
fptr + + ;
2014-04-02 01:46:34 -07:00
if ( ! _eo_do_internal ( eo_id , cur_klass_id , is_super , fptr , pfptr ) )
2014-04-14 02:36:09 -07:00
{
fptr - > o . obj = NULL ;
fptr - > cur_klass = NULL ;
ret = EINA_FALSE ;
}
2013-11-11 02:34:35 -08:00
2014-01-22 02:18:31 -08:00
stack - > frame_ptr + + ;
2013-07-30 06:02:35 -07:00
2014-04-14 02:36:09 -07:00
return ret ;
2013-07-30 06:02:35 -07:00
}
2013-10-02 02:47:10 -07:00
EAPI void
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
_eo_do_end ( void )
2013-07-30 06:02:35 -07:00
{
2014-04-02 01:46:34 -07:00
Eo_Stack_Frame * fptr ;
2014-08-01 03:21:40 -07:00
Eo_Call_Stack * stack = _eo_call_stack_get ( eina_main_loop_is ( ) ) ; // Is it possible to extract information from the scope ?
2013-07-30 06:02:35 -07:00
2014-01-22 02:18:31 -08:00
fptr = stack - > frame_ptr ;
2013-07-30 06:02:35 -07:00
2013-12-30 11:23:22 -08:00
if ( ! _eo_is_a_class ( fptr - > eo_id ) & & fptr - > o . obj )
2013-11-11 02:34:35 -08:00
_eo_unref ( fptr - > o . obj ) ;
2013-07-30 06:02:35 -07:00
2014-04-02 01:46:34 -07:00
fptr - > obj_data = EO_INVALID_DATA ;
2013-07-24 15:10:26 -07:00
2014-01-22 02:18:31 -08:00
if ( fptr = = stack - > frames )
2013-12-30 06:24:15 -08:00
{
2014-09-23 01:29:44 -07:00
CRI ( " eo call stack underflow, abort. " ) ;
2013-12-30 06:24:15 -08:00
abort ( ) ;
}
2014-01-22 02:18:31 -08:00
stack - > frame_ptr - - ;
2013-12-30 06:24:15 -08:00
2014-09-23 01:26:33 -07:00
if ( fptr = = stack - > shrink_frame )
2014-04-02 01:46:34 -07:00
_eo_call_stack_resize ( stack , EINA_FALSE ) ;
2013-07-11 05:15:39 -07:00
}
2013-07-10 00:24:59 -07:00
EAPI Eina_Bool
2014-08-01 03:21:40 -07:00
_eo_call_resolve ( const char * func_name , const Eo_Op op , Eo_Op_Call_Data * call , Eina_Bool is_main_loop , const char * file , int line )
2013-07-09 05:21:11 -07:00
{
2014-04-02 01:46:34 -07:00
Eo_Stack_Frame * fptr ;
2013-07-10 00:24:59 -07:00
const _Eo_Class * klass ;
const op_type_funcs * func ;
2013-11-11 02:34:35 -08:00
Eina_Bool is_obj ;
2013-07-24 15:10:26 -07:00
2014-01-08 03:11:20 -08:00
if ( op = = EO_NOOP ) return EINA_FALSE ;
2014-08-01 03:21:40 -07:00
fptr = _eo_call_stack_get ( is_main_loop ) - > frame_ptr ;
2014-04-14 02:36:09 -07:00
if ( EINA_UNLIKELY ( ! fptr - > o . obj ) )
return EINA_FALSE ;
2013-11-11 02:34:35 -08:00
is_obj = ! _eo_is_a_class ( fptr - > eo_id ) ;
klass = ( is_obj ) ? fptr - > o . obj - > klass : fptr - > o . kls ;
/* If we have a current class, we need to itr to the next. */
if ( fptr - > cur_klass )
{
2014-04-02 01:46:34 -07:00
func = _eo_kls_itr_next ( klass , fptr - > cur_klass , op ) ;
2013-11-11 02:34:35 -08:00
2013-11-11 05:06:51 -08:00
if ( ! func )
2013-12-30 11:31:40 -08:00
goto end ;
2013-11-11 05:06:51 -08:00
klass = func - > src ;
}
else
{
func = _dich_func_get ( klass , 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-11-07 14:38:36 -08:00
call - > klass = _eo_class_id_get ( klass ) ;
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
{
2013-11-07 14:38:36 -08:00
call - > obj = ( Eo * ) fptr - > eo_id ;
2013-11-11 02:34:35 -08:00
if ( func - > src = = fptr - > o . obj - > klass )
2013-07-30 06:02:35 -07:00
{
2014-04-02 01:46:34 -07:00
if ( fptr - > obj_data = = EO_INVALID_DATA )
2013-11-11 02:34:35 -08:00
fptr - > obj_data = _eo_data_scope_get ( fptr - > o . obj , func - > src ) ;
2013-12-25 06:16:34 -08:00
2013-07-30 06:02:35 -07:00
call - > data = fptr - > obj_data ;
}
else
2013-11-11 02:34:35 -08:00
call - > data = _eo_data_scope_get ( fptr - > o . obj , func - > src ) ;
2013-12-25 06:16:34 -08:00
}
else
2013-11-07 14:38:36 -08:00
{
call - > obj = call - > klass ;
call - > data = NULL ;
}
2013-12-25 06:16:34 -08:00
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'. " ,
file , line , func_name , 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 ;
EINA_LIST_FOREACH ( ( ( _Eo_Object * ) fptr - > o . 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
func = _dich_func_get ( emb_obj - > klass , op ) ;
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
{
call - > obj = _eo_id_get ( emb_obj ) ;
call - > klass = _eo_class_id_get ( emb_obj - > klass ) ;
call - > func = func - > func ;
call - > data = _eo_data_scope_get ( emb_obj , func - > src ) ;
return EINA_TRUE ;
}
}
}
2013-11-11 02:34:35 -08:00
{
const _Eo_Class * main_klass ;
main_klass = ( is_obj ) ? fptr - > o . obj - > klass : fptr - > o . kls ;
/* If it's a do_super call. */
if ( fptr - > cur_klass )
{
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'. " ,
2014-01-03 06:54:18 -08:00
file , line , func_name , op , main_klass - > desc - > name ,
2013-12-30 11:31:40 -08:00
fptr - > 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'. " ,
2014-01-03 06:54:18 -08:00
file , line , func_name , 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-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 ) .
*/
2014-04-02 01:46:34 -07:00
static inline const Eo_Op_Description *
2015-06-18 04:30:13 -07:00
_eo_api_desc_get ( const void * api_func , const _Eo_Class * klass , const _Eo_Class * * extns )
2013-12-25 05:51:52 -08:00
{
2013-08-14 04:48:54 -07:00
const _Eo_Class * cur_klass ;
const _Eo_Class * * kls_itr = NULL ;
2014-04-02 01:46:34 -07:00
const Eo_Op_Description * op_desc ;
const Eo_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
{
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 ;
# ifndef _WIN32
int imin , imax , imid ;
2013-11-07 15:42:42 -08:00
imin = 0 ;
imax = cur_klass - > desc - > ops . count - 1 ;
2013-07-25 23:39:34 -07:00
2013-11-07 15:42:42 -08:00
while ( imax > = imin )
{
imid = ( imax + imin ) / 2 ;
op_desc = op_descs + imid ;
if ( op_desc - > api_func > api_func )
imin = imid + 1 ;
else if ( op_desc - > api_func < api_func )
imax = imid - 1 ;
else
return op_desc ;
}
2015-06-18 04:30:13 -07:00
# else
2014-05-19 05:04:32 -07:00
/* 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 .
*/
2014-05-29 03:54:22 -07:00
for ( unsigned int i = 0 ; i < cur_klass - > desc - > ops . count ; i + + )
2015-06-18 05:44:51 -07:00
{
2015-09-28 07:26:51 -07:00
if ( ( ( op_descs [ i ] . api_func ! = NULL ) & & ( op_descs [ i ] . api_func ! = ( ( void ( * ) ( ) ) - 1 ) ) ) & &
( api_func & & ! strcmp ( api_func , op_descs [ i ] . api_func ) ) )
2015-06-18 05:44:51 -07:00
{
return & op_descs [ i ] ;
}
}
2014-05-19 05:04:32 -07:00
# endif
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 ;
}
EAPI Eo_Op
2014-08-01 03:21:40 -07:00
_eo_api_op_id_get ( const void * api_func , Eina_Bool is_main_loop , const char * file , int line )
2013-12-25 07:14:55 -08:00
{
2014-04-02 01:46:34 -07:00
const Eo_Op_Description * desc ;
2013-12-30 11:31:40 -08:00
const _Eo_Class * klass ;
2014-08-01 03:21:40 -07:00
Eo_Call_Stack * stack = _eo_call_stack_get ( is_main_loop ) ;
2013-07-25 17:34:16 -07:00
2014-01-22 02:18:31 -08:00
Eina_Bool class_ref = _eo_is_a_class ( stack - > frame_ptr - > eo_id ) ;
2013-11-07 14:38:36 -08:00
2014-04-14 02:36:09 -07:00
if ( EINA_UNLIKELY ( ! stack - > frame_ptr - > o . obj ) )
return EO_NOOP ;
2013-11-07 14:38:36 -08:00
if ( class_ref )
2014-01-22 02:18:31 -08:00
klass = stack - > frame_ptr - > o . kls ;
2013-07-31 14:37:06 -07:00
else
2014-01-22 02:18:31 -08:00
klass = stack - > frame_ptr - > o . obj - > klass ;
2013-07-25 17:34:16 -07:00
2015-06-18 04:30:13 -07:00
desc = _eo_api_desc_get ( api_func , klass , klass - > extensions ) ;
2013-12-25 07:14:55 -08:00
2013-07-25 17:34:16 -07:00
if ( desc = = NULL )
2013-07-31 14:37:06 -07:00
{
2015-09-28 06:15:15 -07:00
const char * fct_name = _eo_op_desc_name_get ( desc ) ;
2014-05-08 04:44:47 -07:00
ERR ( " in %s:%d: unable to resolve %s api func '%s' %p in class '%s'. " ,
file , line , ( class_ref ? " class " : " regular " ) ,
fct_name , api_func , klass - > desc - > name ) ;
2013-07-31 14:37:06 -07:00
return EO_NOOP ;
}
2013-12-25 07:14:55 -08:00
2013-12-30 11:31:40 -08:00
return desc - > op ;
2013-12-25 05:51:52 -08:00
}
static int
2014-04-02 01:46:34 -07:00
eo_api_funcs_cmp ( const void * p1 , const void * p2 )
2013-12-25 05:51:52 -08:00
{
2014-04-02 01:46:34 -07:00
const Eo_Op_Description * op1 , * op2 ;
op1 = ( Eo_Op_Description * ) p1 ;
op2 = ( Eo_Op_Description * ) p2 ;
2013-12-25 05:51:52 -08:00
if ( op1 - > api_func > op2 - > api_func ) return - 1 ;
else if ( op1 - > api_func < op2 - > api_func ) return 1 ;
else return 0 ;
}
2014-04-03 09:54:30 -07:00
static Eina_Bool
2014-04-02 01:46:34 -07:00
_eo_class_funcs_set ( _Eo_Class * klass )
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 ;
2014-04-02 01:46:34 -07:00
const Eo_Op_Description * api_desc ;
Eo_Op_Description * op_desc ;
Eo_Op_Description * op_descs ;
2013-12-25 05:51:52 -08:00
2014-01-08 02:13:34 -08:00
op_id = klass - > base_id ;
2014-05-07 07:05:26 -07:00
op_descs = klass - > desc - > 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
2014-04-02 01:46:34 -07:00
qsort ( ( void * ) op_descs , klass - > desc - > ops . count , sizeof ( Eo_Op_Description ) , eo_api_funcs_cmp ) ;
2014-01-09 05:43:26 -08:00
2014-01-08 02:13:34 -08:00
last_api_func = NULL ;
2015-09-28 07:48:17 -07:00
for ( i = 0 , op_desc = op_descs ; i < klass - > desc - > ops . count ; i + + , op_desc + + )
2013-12-25 05:51:52 -08:00
{
2013-07-24 15:08:37 -07:00
if ( op_desc - > api_func = = NULL )
2014-01-08 02:13:34 -08:00
{
2014-01-09 05:43:26 -08:00
ERR ( " Class '%s': NULL API not allowed (%d NULL->%p '%s'). " ,
2015-09-28 06:15:15 -07:00
klass - > desc - > name , op_desc - > op , 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
2013-12-25 05:51:52 -08:00
if ( op_desc - > op = = EO_NOOP )
{
2014-01-08 02:13:34 -08:00
if ( op_desc - > api_func = = last_api_func )
{
2014-01-09 05:43:26 -08:00
ERR ( " Class '%s': API previously defined (%d %p->%p '%s'). " ,
2015-09-28 06:15:15 -07:00
klass - > desc - > name , op_desc - > op , 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-07-24 15:08:37 -07:00
op_desc - > op = op_id ;
op_id + + ;
}
2014-04-02 01:46:34 -07:00
else if ( op_desc - > op = = EO_OP_OVERRIDE )
2013-07-24 15:08:37 -07:00
{
2015-06-18 04:30:13 -07:00
api_desc = _eo_api_desc_get ( op_desc - > api_func , klass - > parent , 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). " ,
2015-09-28 06:15:15 -07:00
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
op_desc - > op = api_desc - > op ;
2013-12-25 05:51:52 -08:00
}
2013-07-24 15:08:37 -07:00
2015-09-28 06:15:15 -07:00
DBG ( " %4d %p->%p '%s' " , op_desc - > op , op_desc - > api_func , op_desc - > func , _eo_op_desc_name_get ( op_desc ) ) ;
2014-01-08 02:13:34 -08:00
2014-01-09 05:43:26 -08:00
if ( ! _dich_func_set ( klass , op_desc - > op , op_desc - > func ) )
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 *
2014-10-10 01:30:52 -07:00
_eo_add_internal_start ( const char * file , int line , const Eo_Class * klass_id , Eo * parent_id , Eina_Bool ref )
2013-08-01 00:47:21 -07:00
{
2013-12-26 15:00:11 -08:00
_Eo_Object * obj ;
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 ) ;
}
if ( EINA_UNLIKELY ( klass - > desc - > type ! = EO_CLASS_TYPE_REGULAR ) )
{
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 ;
# 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 ) ;
Eo * eo_id = _eo_id_get ( obj ) ;
2013-08-01 00:47:21 -07:00
_eo_condtor_reset ( obj ) ;
2013-12-26 15:00:11 -08:00
_eo_ref ( obj ) ;
2014-09-25 07:51:17 -07:00
eo_do ( eo_id , eo_parent_set ( parent_id ) ) ;
2013-12-26 12:11:48 -08:00
2015-08-26 02:47:06 -07:00
/* If there's a parent. Ref. Eo_add should return an object with either a
2014-09-25 07:51:17 -07:00
* parent ref , or with the lack of , just a ref . */
{
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
Eo * parent_tmp ;
2015-08-26 02:47:06 -07:00
if ( ref & & eo_do_ret ( eo_id , parent_tmp , eo_parent_get ( ) ) )
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
{
2015-08-26 02:47:06 -07:00
_eo_ref ( obj ) ;
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
}
2014-09-25 07:51:17 -07:00
}
2015-05-19 03:41:27 -07:00
/* eo_id can change here. Freeing is done on the resolved object. */
eo_do ( eo_id , eo_id = eo_constructor ( ) ) ;
if ( ! eo_id )
{
ERR ( " Object of class '%s' - Error while constructing object " ,
klass - > desc - > name ) ;
_eo_unref ( obj ) ;
2015-05-20 08:48:20 -07:00
eo_del ( ( Eo * ) obj - > header . id ) ;
2015-05-19 03:41:27 -07:00
return NULL ;
}
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 *
2014-05-30 03:17:36 -07:00
_eo_add_internal_end ( Eo * eo_id )
2013-08-01 00:47:21 -07:00
{
2014-04-02 01:46:34 -07:00
Eo_Stack_Frame * fptr ;
2014-08-01 03:21:40 -07:00
Eo_Call_Stack * stack = _eo_call_stack_get ( eina_main_loop_is ( ) ) ;
2013-08-01 00:47:21 -07:00
2014-01-22 02:18:31 -08:00
fptr = stack - > frame_ptr ;
2013-08-01 00:47:21 -07:00
2015-05-20 06:56:45 -07:00
if ( ( fptr = = NULL ) | | ( eo_id & & ( fptr - > eo_id ! = eo_id ) ) )
2013-08-01 00:47:21 -07:00
{
2014-05-30 03:17:36 -07:00
ERR ( " Something very wrong happend to the call stack. " ) ;
2013-08-01 00:47:21 -07:00
return NULL ;
}
2014-04-14 02:36:09 -07:00
if ( EINA_UNLIKELY ( ! fptr - > o . obj ) )
2015-01-23 08:51:02 -08:00
{
2015-05-21 02:52:26 -07:00
ERR ( " Corrupt call stack, shouldn't happen, please report! " ) ;
2015-01-23 08:51:02 -08:00
return NULL ;
}
2014-04-14 02:36:09 -07:00
2013-08-01 00:47:21 -07:00
{
2013-11-11 02:34:35 -08:00
const _Eo_Class * klass = ( fptr - > cur_klass ) ?
fptr - > cur_klass : fptr - > o . obj - > klass ;
2015-05-20 06:56:45 -07:00
if ( ! fptr - > o . obj - > condtor_done )
{
ERR ( " Object of class '%s' - Not all of the object constructors have been executed. " ,
klass - > desc - > name ) ;
goto cleanup ;
}
if ( ! eo_id )
{
2015-06-24 02:35:46 -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);
2015-05-20 06:56:45 -07:00
goto cleanup ;
}
2013-08-01 00:47:21 -07:00
}
2014-08-29 01:55:02 -07:00
fptr - > o . obj - > finalized = EINA_TRUE ;
2013-11-11 02:34:35 -08:00
_eo_unref ( fptr - > o . obj ) ;
2013-12-26 15:00:11 -08:00
return ( Eo * ) eo_id ;
2015-05-20 06:56:45 -07:00
cleanup :
_eo_unref ( fptr - > o . obj ) ;
2015-05-20 08:48:20 -07:00
eo_del ( ( Eo * ) fptr - > o . 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 *
_eo_add_end ( void )
{
Eo * ret = eo_finalize ( ) ;
2015-05-20 06:56:45 -07:00
ret = _eo_add_internal_end ( ret ) ;
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
_eo_do_end ( ) ;
return ret ;
}
2013-07-18 00:10:07 -07:00
/*****************************************************************************/
2013-04-17 07:08:12 -07:00
# define _EO_OP_ERR_NO_OP_PRINT(file, line, op, klass) \
2012-05-15 08:06:40 -07:00
do \
{ \
2013-04-18 04:19:02 -07:00
const _Eo_Class * op_klass = _eo_op_class_get ( op ) ; \
2012-05-15 08:06:40 -07:00
const char * _dom_name = ( op_klass ) ? op_klass - > desc - > name : NULL ; \
2013-06-03 04:30:19 -07:00
ERR ( " in %s:%d: Can't execute function %s:%s (op 0x%x) for class '%s'. Aborting. " , \
2014-04-01 08:21:13 -07:00
file , line , _dom_name , _eo_op_id_name_get ( op ) , op , \
2012-05-15 08:06:40 -07:00
( klass ) ? klass - > desc - > name : NULL ) ; \
} \
while ( 0 )
2012-05-15 07:16:58 -07:00
2013-09-27 08:38:15 -07:00
EAPI const Eo_Class *
2013-12-26 14:46:50 -08:00
eo_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 ) ;
2014-06-02 05:09:21 -07:00
return EO_ABSTRACT_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
2013-04-18 04:19:02 -07:00
if ( obj - > klass )
return _eo_class_id_get ( obj - > klass ) ;
return NULL ;
2012-04-05 08:31:15 -07:00
}
EAPI const char *
2013-12-26 14:46:50 -08:00
eo_class_name_get ( const Eo_Class * eo_id )
2012-04-05 08:31:15 -07:00
{
2013-09-26 15:13:00 -07:00
const _Eo_Class * klass ;
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 ;
}
else
{
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 ;
}
static void
2013-04-18 04:19:02 -07:00
_eo_class_base_op_init ( _Eo_Class * klass )
2012-04-05 08:31:15 -07:00
{
2012-05-01 00:40:14 -07:00
const Eo_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 ;
klass - > chain_size = DICH_CHAIN1 ( _eo_ops_last_id ) + 1 ;
klass - > chain = calloc ( klass - > chain_size , sizeof ( * klass - > chain ) ) ;
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
2013-04-18 04:19:02 -07:00
_eo_class_mro_has ( const _Eo_Class * klass , const _Eo_Class * find )
2012-06-14 03:29:39 -07:00
{
2013-04-18 04:19:02 -07:00
const _Eo_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 *
2013-04-18 04:19:02 -07:00
_eo_class_mro_add ( Eina_List * mro , const _Eo_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
{
2013-04-18 04:19:02 -07:00
const _Eo_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
{
2013-04-18 04:19:02 -07:00
const _Eo_Class * extn = * extn_itr ;
2013-06-17 14:41:02 -07:00
if ( extn - > desc - > type = = EO_CLASS_TYPE_MIXIN )
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 *
_eo_class_mro_init ( const Eo_Class_Description * desc , const _Eo_Class * parent , Eina_List * extensions )
{
Eina_List * mro = NULL ;
Eina_List * extn_itr = NULL ;
Eina_List * extn_pos = NULL ;
const _Eo_Class * extn = NULL ;
/* Add MIXINS extensions. */
EINA_LIST_FOREACH ( extensions , extn_itr , extn )
2012-04-19 01:52:15 -07:00
{
2013-06-17 14:41:02 -07:00
if ( extn - > desc - > type ! = EO_CLASS_TYPE_MIXIN )
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
{
2012-06-13 04:39:02 -07:00
if ( extn - > desc - > type ! = EO_CLASS_TYPE_MIXIN )
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
2013-04-18 04:19:02 -07:00
_eo_class_constructor ( _Eo_Class * klass )
2012-04-05 08:31:15 -07:00
{
if ( klass - > constructed )
2013-07-29 14:52:46 -07:00
return ;
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
2013-04-18 04:19:02 -07:00
eo_class_free ( _Eo_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
2012-05-07 23:56:57 -07:00
_dich_func_clean_all ( klass ) ;
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
2013-12-26 14:46:50 -08:00
_eo_class_isa_func ( Eo * eo_id EINA_UNUSED , void * class_data EINA_UNUSED , va_list * list EINA_UNUSED )
2012-06-13 04:39:12 -07:00
{
/* Do nonthing. */
}
2013-09-27 08:38:15 -07:00
EAPI const Eo_Class *
eo_class_new ( const Eo_Class_Description * desc , const Eo_Class * parent_id , . . . )
2012-04-05 08:31:15 -07:00
{
2013-04-18 04:19:02 -07:00
_Eo_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 ) ;
2013-04-18 04:19:02 -07:00
_Eo_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. */
2012-05-01 00:40:14 -07:00
if ( desc - > type = = EO_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 )
{
case EO_CLASS_TYPE_REGULAR :
case EO_CLASS_TYPE_REGULAR_NO_INSTANT :
if ( ( parent - > desc - > type ! = EO_CLASS_TYPE_REGULAR ) & &
( parent - > desc - > type ! = EO_CLASS_TYPE_REGULAR_NO_INSTANT ) )
{
ERR ( " Regular classes ('%s') aren't allowed to inherit from non-regular classes ('%s'). " ,
desc - > name , parent - > desc - > name ) ;
return NULL ;
}
break ;
case EO_CLASS_TYPE_INTERFACE :
case EO_CLASS_TYPE_MIXIN :
if ( ( parent - > desc - > type ! = EO_CLASS_TYPE_INTERFACE ) & &
( parent - > desc - > type ! = EO_CLASS_TYPE_MIXIN ) )
{
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 ;
2013-04-18 04:19:02 -07:00
const _Eo_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
{
2013-09-27 08:38:15 -07:00
extn = _eo_class_pointer_get ( ( Eo_Class * ) extn_id ) ;
2012-04-05 08:31:15 -07:00
switch ( extn - > desc - > type )
{
2012-05-01 00:40:14 -07:00
case EO_CLASS_TYPE_REGULAR_NO_INSTANT :
2014-02-18 07:02:56 -08:00
case EO_CLASS_TYPE_REGULAR :
2012-06-13 04:39:02 -07:00
case EO_CLASS_TYPE_INTERFACE :
2012-05-01 00:40:14 -07:00
case EO_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 ) ;
2013-06-17 14:35:48 -07:00
extn_sz = sizeof ( _Eo_Class * ) * ( eina_list_count ( extn_list ) + 1 ) ;
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 ;
}
mro_sz = sizeof ( _Eo_Class * ) * ( eina_list_count ( mro ) + 1 ) ;
DBG ( " Finished building MRO list for class '%s' " , desc - > name ) ;
}
2013-06-17 14:48:22 -07:00
/* Prepare mixins list */
{
Eina_List * itr ;
const _Eo_Class * kls_itr ;
DBG ( " Started building Mixins list for class '%s' " , desc - > name ) ;
mixins = NULL ;
EINA_LIST_FOREACH ( mro , itr , kls_itr )
{
if ( ( kls_itr ) & & ( kls_itr - > desc - > type = = EO_CLASS_TYPE_MIXIN ) & &
( 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 ) ;
if ( ( desc - > type = = EO_CLASS_TYPE_MIXIN ) & & ( desc - > data_size > 0 ) )
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 ;
klass - > extensions = ( const _Eo_Class * * ) ( ( char * ) klass + _eo_class_sz ) ;
2013-06-17 14:41:02 -07:00
klass - > mro = ( const _Eo_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 ) ;
}
2013-06-17 14:41:02 -07:00
mro = eina_list_remove ( mro , NULL ) ;
mro = eina_list_prepend ( mro , klass ) ;
2013-06-17 14:48:22 -07:00
if ( ( desc - > type = = EO_CLASS_TYPE_MIXIN ) & & ( desc - > data_size > 0 ) )
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 */
{
const _Eo_Class * extn = NULL ;
const _Eo_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
{
2013-06-17 14:48:22 -07:00
const _Eo_Class * kls_itr = NULL ;
2013-06-17 14:41:02 -07:00
const _Eo_Class * * mro_itr = klass - > mro ;
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 ;
if ( klass - > desc - > type ! = EO_CLASS_TYPE_MIXIN )
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
{
2013-06-17 14:48:22 -07:00
const _Eo_Class * kls_itr = NULL ;
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
}
2013-06-17 14:32:50 -07:00
klass - > obj_size = _eo_sz + 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 */
{
2013-04-18 04:19:02 -07:00
const _Eo_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
{
_dich_copy_all ( klass , * mro_itr ) ;
}
}
2012-06-13 04:39:12 -07:00
/* Mark which classes we implement */
{
2013-04-18 04:19:02 -07:00
const _Eo_Class * * extn_itr ;
2012-06-13 04:39:12 -07:00
for ( extn_itr = klass - > extensions ; * extn_itr ; extn_itr + + )
{
2013-04-18 04:19:02 -07:00
const _Eo_Class * extn = * extn_itr ;
2012-06-13 04:39:12 -07:00
/* Set it in the dich. */
2012-07-10 07:01:45 -07:00
_dich_func_set ( klass , extn - > base_id +
extn - > desc - > ops . count , _eo_class_isa_func ) ;
2012-06-13 04:39:12 -07:00
}
2012-07-10 07:01:45 -07:00
_dich_func_set ( klass , klass - > base_id + klass - > desc - > ops . count ,
_eo_class_isa_func ) ;
2012-06-13 04:39:12 -07:00
if ( klass - > parent )
{
_dich_func_set ( 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
}
}
2014-04-02 01:46:34 -07:00
if ( ! _eo_class_funcs_set ( klass ) )
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 ) ;
_dich_func_clean_all ( klass ) ;
free ( klass ) ;
2014-05-01 05:28:16 -07:00
return NULL ;
2014-01-09 05:42:17 -08:00
}
2013-10-10 01:26:02 -07:00
eina_spinlock_take ( & _eo_class_creation_lock ) ;
2014-03-11 08:50:44 -07:00
klass - > header . id = + + _eo_classes_last_id | MASK_CLASS_TAG ;
2013-03-12 03:16:43 -07:00
{
2013-06-17 15:08:58 -07:00
/* FIXME: Handle errors. */
size_t arrsize = _eo_classes_last_id * sizeof ( * _eo_classes ) ;
_Eo_Class * * tmp ;
tmp = realloc ( _eo_classes , arrsize ) ;
/* If it's the first allocation, memset. */
if ( ! _eo_classes )
memset ( tmp , 0 , arrsize ) ;
_eo_classes = tmp ;
2015-01-08 04:40:56 -08:00
_eo_classes [ _UNMASK_ID ( klass - > header . id ) - 1 ] = klass ;
2013-03-12 03:16:43 -07:00
}
2013-10-10 01:26:02 -07:00
eina_spinlock_release ( & _eo_class_creation_lock ) ;
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
}
2012-06-13 04:39:12 -07:00
EAPI Eina_Bool
2013-12-26 14:46:50 -08:00
eo_isa ( const Eo * eo_id , const Eo_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 ) ;
2012-06-13 04:39:12 -07:00
const op_type_funcs * func = _dich_func_get ( obj - > klass ,
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 *
2013-04-18 04:19:02 -07:00
eo_xref_internal ( const char * file , int line , 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_VAL ( obj_id , obj , obj_id ) ;
2012-04-23 01:10:04 -07:00
2012-05-06 05:03:26 -07:00
_eo_ref ( obj ) ;
2012-04-17 08:22:22 -07:00
2013-01-18 08:57:57 -08:00
# ifdef EO_DEBUG
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
2013-04-18 04:19:02 -07:00
eo_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
2012-05-06 05:03:26 -07:00
_eo_unref ( obj ) ;
}
2012-05-01 00:40:14 -07:00
EAPI Eo *
2013-04-18 04:19:02 -07:00
eo_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
2013-04-18 04:19:02 -07:00
_eo_ref ( obj ) ;
return ( Eo * ) obj_id ;
2012-04-05 08:31:15 -07:00
}
2012-05-06 05:03:26 -07:00
EAPI void
2013-04-18 04:19:02 -07:00
eo_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
_eo_unref ( obj ) ;
}
2012-06-07 00:17:45 -07:00
EAPI void
eo_del ( const Eo * obj )
{
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
Eo * parent_tmp ;
if ( eo_do_ret ( obj , parent_tmp , eo_parent_get ( ) ) )
2014-09-30 06:27:43 -07:00
{
eo_do ( obj , eo_parent_set ( NULL ) ) ;
}
else
{
eo_unref ( obj ) ;
}
2012-06-07 00:17:45 -07:00
}
2012-04-11 00:05:37 -07:00
EAPI int
2013-04-18 04:19:02 -07:00
eo_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
2012-04-11 00:05:37 -07:00
return obj - > refcount ;
}
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 ;
}
2012-05-06 05:03:21 -07:00
static inline void *
2013-09-26 14:31:39 -07:00
_eo_data_scope_get ( const _Eo_Object * obj , const _Eo_Class * klass )
2012-04-05 08:31:15 -07:00
{
2013-08-09 06:58:55 -07:00
if ( EINA_LIKELY ( ( klass - > desc - > data_size > 0 ) & & ( klass - > desc - > type ! = EO_CLASS_TYPE_MIXIN ) ) )
return ( ( char * ) obj ) + _eo_sz + klass - > data_offset ;
if ( EINA_UNLIKELY ( klass - > desc - > data_size = = 0 ) )
return NULL ;
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 )
return ( ( char * ) obj ) + _eo_sz + doff_itr - > offset ;
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 *
2013-09-26 14:31:39 -07:00
_eo_data_xref_internal ( const char * file , int line , _Eo_Object * obj , const _Eo_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 )
{
data = _eo_data_scope_get ( obj , klass ) ;
if ( data = = NULL ) return NULL ;
}
( obj - > datarefcount ) + + ;
# ifdef EO_DEBUG
Eo_Xref_Node * xref = calloc ( 1 , sizeof ( * xref ) ) ;
2013-09-27 03:13:14 -07:00
xref - > ref_obj = _eo_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
2013-09-26 14:31:39 -07:00
_eo_data_xunref_internal ( _Eo_Object * obj , void * data , const _Eo_Object * ref_obj )
2013-03-19 23:56:15 -07:00
{
# ifdef EO_DEBUG
const _Eo_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
( void ) data ;
# endif
if ( obj - > datarefcount = = 0 )
{
2014-05-29 03:54:22 -07:00
ERR ( " Data for object %zx (%s) is already not referenced. " , ( size_t ) _eo_id_get ( obj ) , obj - > klass - > desc - > name ) ;
2013-03-19 23:56:15 -07:00
}
else
{
( obj - > datarefcount ) - - ;
}
# ifdef EO_DEBUG
Eo_Xref_Node * xref = NULL ;
EINA_INLIST_FOREACH ( obj - > data_xrefs , xref )
{
2013-09-27 03:13:14 -07:00
if ( xref - > ref_obj = = _eo_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
{
2014-05-29 03:54:22 -07:00
ERR ( " ref_obj (0x%zx) does not reference data (%p) of obj (0x%zx). " , ( size_t ) _eo_id_get ( ref_obj ) , data , ( size_t ) _eo_id_get ( obj ) ) ;
2013-03-19 23:56:15 -07:00
}
# else
( void ) ref_obj ;
# endif
}
2012-05-06 05:03:21 -07:00
EAPI void *
2013-09-27 08:38:15 -07:00
eo_data_get ( const Eo * obj_id , const Eo_Class * klass_id )
2013-03-19 23:56:15 -07:00
{
return eo_data_scope_get ( obj_id , klass_id ) ;
}
EAPI void *
2013-09-27 08:38:15 -07:00
eo_data_scope_get ( const Eo * obj_id , const Eo_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
2013-03-19 23:56:15 -07:00
ret = _eo_data_scope_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 *
2013-09-27 08:38:15 -07:00
eo_data_xref_internal ( const char * file , int line , const Eo * obj_id , const Eo_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 ) ;
_Eo_Class * klass = NULL ;
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
}
ret = _eo_data_xref_internal ( file , line , obj , klass , ref_obj ) ;
# 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
eo_data_xunref_internal ( const Eo * obj_id , void * data , const Eo * ref_obj_id )
{
EO_OBJ_POINTER_RETURN ( obj_id , obj ) ;
EO_OBJ_POINTER_RETURN ( ref_obj_id , ref_obj ) ;
_eo_data_xunref_internal ( obj , data , ref_obj ) ;
}
2012-04-05 08:31:15 -07:00
EAPI Eina_Bool
2012-05-01 00:40:14 -07:00
eo_init ( void )
2012-04-05 08:31:15 -07:00
{
2012-05-01 00:40:14 -07:00
const char * log_dom = " eo " ;
if ( _eo_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 ) ) ;
_eo_class_sz = EO_ALIGN_SIZE ( sizeof ( _Eo_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 ;
2012-07-10 07:01:45 -07:00
_eo_ops_last_id = EO_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 ;
}
2013-10-10 01:26:02 -07:00
if ( ! eina_spinlock_new ( & _eo_class_creation_lock ) )
2012-04-23 01:09:54 -07:00
{
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
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 . */
_eo_class_isa_func ( NULL , NULL , NULL ) ;
# endif
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
2013-10-12 14:51:59 -07:00
/* bootstrap EO_CLASS_CLASS */
2014-06-02 05:09:21 -07:00
( void ) EO_ABSTRACT_CLASS_CLASS ;
2013-10-12 14:51:59 -07:00
2014-04-02 01:46:34 -07:00
if ( _eo_call_stack_key ! = 0 )
WRN ( " _eo_call_stack_key already set, this should not happen. " ) ;
2014-01-22 02:18:31 -08:00
else
2013-10-02 05:57:45 -07:00
{
2014-04-02 01:46:34 -07:00
if ( ! eina_tls_cb_new ( & _eo_call_stack_key , _eo_call_stack_free ) )
2014-01-22 02:18:31 -08:00
{
EINA_LOG_ERR ( " Could not create TLS key for call stack. " ) ;
return EINA_FALSE ;
}
2013-10-02 05:57:45 -07:00
}
2012-04-05 08:31:15 -07:00
return EINA_TRUE ;
}
EAPI Eina_Bool
2012-05-01 00:40:14 -07:00
eo_shutdown ( void )
2012-04-05 08:31:15 -07:00
{
2012-05-06 05:03:23 -07:00
size_t i ;
2013-04-18 04:19:02 -07:00
_Eo_Class * * cls_itr = _eo_classes ;
2012-04-05 08:31:15 -07:00
2012-05-01 00:40:14 -07:00
if ( - - _eo_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
2012-05-01 00:40:14 -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
}
2012-05-01 00:40:14 -07:00
if ( _eo_classes )
2013-04-02 17:31:17 -07:00
free ( _eo_classes ) ;
2012-04-05 08:31:15 -07:00
2013-10-10 01:26:02 -07:00
eina_spinlock_free ( & _eo_class_creation_lock ) ;
2012-04-23 01:09:54 -07:00
2014-04-02 01:46:34 -07:00
if ( _eo_call_stack_key ! = 0 )
eina_tls_free ( _eo_call_stack_key ) ;
2013-10-02 05:57:45 -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
eina_shutdown ( ) ;
return EINA_TRUE ;
}
2012-09-12 04:31:58 -07:00
EAPI Eina_Bool
2013-04-18 04:19:02 -07:00
eo_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
2013-04-18 04:19:02 -07:00
eo_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
2013-04-18 04:19:02 -07:00
eo_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 )
{
2012-06-06 04:41:56 -07:00
ERR ( " Tried to manually free the object %p while the option has not been set; see eo_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
}
2013-01-28 22:36:23 -08:00