efl/src/lib/eo/eo_base_class.c

2853 lines
84 KiB
C
Raw Normal View History

2013-12-25 06:13:41 -08:00
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include <Eina.h>
#include <fnmatch.h>
2013-12-25 06:13:41 -08:00
#include <Eo.h>
#include "eo_internal.h"
2013-12-25 06:13:41 -08:00
#include "eo_ptr_indirection.h"
#include "eo_private.h"
#include "eina_promise_private.h"
2013-12-25 06:13:41 -08:00
eo: Rename EAPI macro to EO_API in Eo library Summary: Patch from a series of patches to rename EAPI symbols to specific library DSOs. = The Rationale = This patch is from a series of patches to rename EAPI symbols to specific library DSOs. EAPI was designed to be able to pass `__attribute__ ((visibility ("default")))` for symbols with GCC, which would mean that even if -fvisibility=hidden was used when compiling the library, the needed symbols would get exported. MSVC __almost__ works like GCC (or mingw) in which you can declare everything as export and it will just work (slower, but it will work). But there's a caveat: global variables will not work the same way for MSVC, but works for mingw and GCC. For global variables (as opposed to functions), MSVC requires correct DSO visibility for MSVC: instead of declaring a symbol as export for everything, you need to declare it as import when importing from another DSO and export when defining it locally. With current EAPI definitions, we get the following example working in mingw and MSVC (observe it doesn't define any global variables as exported symbols). Example 1: dll1: ``` EAPI void foo(void); EAPI void bar() { foo(); } ``` dll2: ``` EAPI void foo() { printf ("foo\n"); } ``` This works fine with API defined as __declspec(dllexport) in both cases and for gcc defining as `__atttribute__((visibility("default")))`. However, the following: Example 2: dll1: ``` EAPI extern int foo; EAPI void foobar(void); EAPI void bar() { foo = 5; foobar(); } ``` dll2: ``` EAPI int foo = 0; EAPI void foobar() { printf ("foo %d\n", foo); } ``` This will work on mingw but will not work for MSVC. And that's why LIBAPI is the only solution that works for MSVC. Co-authored-by: João Paulo Taylor Ienczak Zanette <jpaulotiz@gmail.com> Co-authored-by: Lucas Cavalcante de Sousa <lucks.sousa@gmail.com> Co-authored-by: Ricardo Campos <ricardo.campos@expertise.dev> Reviewers: jptiz, lucas, vtorri, woohyun Reviewed By: jptiz, lucas, vtorri Subscribers: cedric, #reviewers, #committers Tags: #efl Differential Revision: https://phab.enlightenment.org/D12203
2020-12-09 08:50:29 -08:00
EO_API const Efl_Event_Description _EFL_EVENT_CALLBACK_ADD =
EFL_EVENT_DESCRIPTION_HOT("callback,add");
eo: Rename EAPI macro to EO_API in Eo library Summary: Patch from a series of patches to rename EAPI symbols to specific library DSOs. = The Rationale = This patch is from a series of patches to rename EAPI symbols to specific library DSOs. EAPI was designed to be able to pass `__attribute__ ((visibility ("default")))` for symbols with GCC, which would mean that even if -fvisibility=hidden was used when compiling the library, the needed symbols would get exported. MSVC __almost__ works like GCC (or mingw) in which you can declare everything as export and it will just work (slower, but it will work). But there's a caveat: global variables will not work the same way for MSVC, but works for mingw and GCC. For global variables (as opposed to functions), MSVC requires correct DSO visibility for MSVC: instead of declaring a symbol as export for everything, you need to declare it as import when importing from another DSO and export when defining it locally. With current EAPI definitions, we get the following example working in mingw and MSVC (observe it doesn't define any global variables as exported symbols). Example 1: dll1: ``` EAPI void foo(void); EAPI void bar() { foo(); } ``` dll2: ``` EAPI void foo() { printf ("foo\n"); } ``` This works fine with API defined as __declspec(dllexport) in both cases and for gcc defining as `__atttribute__((visibility("default")))`. However, the following: Example 2: dll1: ``` EAPI extern int foo; EAPI void foobar(void); EAPI void bar() { foo = 5; foobar(); } ``` dll2: ``` EAPI int foo = 0; EAPI void foobar() { printf ("foo %d\n", foo); } ``` This will work on mingw but will not work for MSVC. And that's why LIBAPI is the only solution that works for MSVC. Co-authored-by: João Paulo Taylor Ienczak Zanette <jpaulotiz@gmail.com> Co-authored-by: Lucas Cavalcante de Sousa <lucks.sousa@gmail.com> Co-authored-by: Ricardo Campos <ricardo.campos@expertise.dev> Reviewers: jptiz, lucas, vtorri, woohyun Reviewed By: jptiz, lucas, vtorri Subscribers: cedric, #reviewers, #committers Tags: #efl Differential Revision: https://phab.enlightenment.org/D12203
2020-12-09 08:50:29 -08:00
EO_API const Efl_Event_Description _EFL_EVENT_CALLBACK_DEL =
EFL_EVENT_DESCRIPTION_HOT("callback,del");
2013-12-25 06:13:41 -08:00
static int event_freeze_count = 0;
typedef struct _Eo_Callback_Description Eo_Callback_Description;
typedef struct _Efl_Event_Callback_Frame Efl_Event_Callback_Frame;
typedef struct _Efl_Event_Forwarder Efl_Event_Forwarder;
struct _Efl_Event_Forwarder
{
const Efl_Event_Description *desc;
Eo *source;
Eo *new_obj;
short priority;
Eina_Bool inserted : 1;
};
2013-12-25 06:13:41 -08:00
struct _Efl_Event_Callback_Frame
{
eo: event callback call optimization a little overfiew to how eos event emission is working: - In eo there are 2 types of events restart events and normal events. Normals are *always* emitted from callback_max to 0 Restarts are emitted from the previous emissions current idx to 0. The previous emission will stop then - To keep track of the previous event emissions for restarts there was an eina inlist. - To keep track of other things in eo, there was an additional eo event stack frame (newly inserted events etc. etc.) This commit now uses this event stack frame for implementing the details about the restart events. This has the advatage that every efl_object_data contains one byte less, and the up to date keeping of the id's in the restart infrastructure is not needed anymore, making the whole event emission code less instructions and faster. How this now works: - Every emission has a event emission frame, when the emission starts, the frame is added, next points to the next older event emission. In this event stack frame we are storing the current idx, the description and a few other things that are not really relevant at this point. - when a restart event is started, this event stack is searched from the current frame up to the next one featuring the same event description. The event frame stack is then remembered, if the event emission is done, the current idx (normally 0 or something higher when callback was stopped) is then copyied back to the earlier frame. - Based on the nature of the event frame stacks, the idx is updated every iteration. And for the restart events, we only need to know the next, which removes the need of permanently updating the idx in the current stack. - The event frame stack is not allocated on the heap, hence more things in there does not matter at all. Reviewed-by: Cedric BAIL <cedric.bail@free.fr> Differential Revision: https://phab.enlightenment.org/D12097
2020-08-05 01:45:29 -07:00
const Efl_Event_Description *desc;
Efl_Event_Callback_Frame *next;
unsigned int idx;
unsigned int inserted_before;
unsigned short generation;
};
typedef struct
{
const char *name;
const char *comment;
Eo *composite_parent;
Eina_Inlist *generic_data;
Eo ***wrefs;
Eina_Hash *providers;
Eina_Hash *schedulers;
Eina_Hash *forwarders;
} Efl_Object_Extension;
#define EFL_OBJECT_EVENT_CALLBACK(Event) Eina_Bool event_cb_##Event : 1;
struct _Efl_Object_Data
2013-12-25 06:13:41 -08:00
{
Eina_Inlist *children;
Eo *parent;
Efl_Object_Extension *ext;
Efl_Event_Callback_Frame *event_frame;
Eo_Callback_Description **callbacks;
#ifdef EFL64
uint64_t callbacks_mask;
#else
uint32_t callbacks_mask;
#endif
Eina_Inlist *pending_futures;
unsigned int callbacks_count;
unsigned short event_freeze_count;
EFL_OBJECT_EVENT_CALLBACK(EFL_EVENT_CALLBACK_ADD);
EFL_OBJECT_EVENT_CALLBACK(EFL_EVENT_CALLBACK_DEL);
EFL_OBJECT_EVENT_CALLBACK(EFL_EVENT_DEL);
EFL_OBJECT_EVENT_CALLBACK(EFL_EVENT_NOREF);
EFL_OBJECT_EVENT_CALLBACK(EFL_EVENT_INVALIDATE);
EFL_OBJECT_EVENT_CALLBACK(EFL_EVENT_DESTRUCT); // No proper count: minor optimization triggered at destruction only
Eina_Bool callback_stopped : 1;
Eina_Bool need_cleaning : 1;
Eina_Bool allow_parent_unref : 1; // Allows unref to zero even with a parent
};
2013-12-25 06:13:41 -08:00
typedef enum
{
DATA_PTR,
DATA_OBJ,
DATA_OBJ_WEAK,
DATA_VAL
} Eo_Generic_Data_Node_Type;
2013-12-25 06:13:41 -08:00
typedef struct
{
EINA_INLIST;
const Eo *obj;
Eina_Stringshare *key;
union {
Eina_Value *val;
Eo *obj;
void *ptr;
} d;
Eo_Generic_Data_Node_Type d_type;
2013-12-25 06:13:41 -08:00
} Eo_Generic_Data_Node;
typedef struct _Efl_Future_Pending
{
EINA_INLIST;
const Eo *o;
Eina_Future *future;
Efl_Future_Cb_Desc desc;
} Efl_Future_Pending;
typedef struct
{
EINA_INLIST;
const Efl_Event_Description *desc;
unsigned int current;
} Eo_Current_Callback_Description;
#define EVENT_STACK_PUSH(pd, fr) do { \
(fr)->next = (pd)->event_frame; \
(pd)->event_frame = (fr); \
} while (0)
#define EVENT_STACK_POP(pd) do { \
if ((pd)->event_frame) (pd)->event_frame = (pd)->event_frame->next; \
} while (0)
static void _efl_event_forwarder_callback(void *data, const Efl_Event *event);
static int _eo_nostep_alloc = -1;
static void
_efl_pending_futures_clear(Efl_Object_Data *pd)
{
while (pd->pending_futures)
{
Efl_Future_Pending *pending = EINA_INLIST_CONTAINER_GET(pd->pending_futures, Efl_Future_Pending);
Eina_Future *future = *pending->desc.storage;
assert(future);
eina_future_cancel(future);
}
}
static inline void
_efl_object_extension_free(Efl_Object_Extension *ext)
{
eina_freeq_ptr_main_add(ext, free, sizeof(*ext));
}
static inline Efl_Object_Extension *
_efl_object_extension_need(Efl_Object_Data *pd)
{
if (!pd->ext) pd->ext = calloc(1, sizeof(Efl_Object_Extension));
return pd->ext;
}
static inline void
_efl_object_extension_noneed(Efl_Object_Data *pd)
{
Efl_Object_Extension *ext = pd->ext;
if ((!ext) ||
(ext->name) ||
(ext->comment) ||
(ext->generic_data) ||
(ext->wrefs) ||
(ext->composite_parent) ||
(ext->providers) ||
(ext->schedulers) ||
(ext->forwarders)) return;
_efl_object_extension_free(pd->ext);
pd->ext = NULL;
}
static void
_efl_object_invalidate(Eo *obj_id, Efl_Object_Data *pd)
{
_efl_pending_futures_clear(pd);
if (pd->ext && pd->ext->forwarders)
{
eina_hash_free(pd->ext->forwarders);
pd->ext->forwarders = NULL;
_efl_object_extension_noneed(pd);
}
if (pd->ext && pd->ext->providers)
{
eina_hash_free(pd->ext->providers);
pd->ext->providers = NULL;
_efl_object_extension_noneed(pd);
}
if (pd->ext && pd->ext->schedulers)
{
eina_hash_free(pd->ext->schedulers);
pd->ext->schedulers = NULL;
_efl_object_extension_noneed(pd);
}
EO_OBJ_POINTER_RETURN(obj_id, obj);
// Finally invalidate itself if it wasn't done already
// I am not sure this is a good idea, but it force the
// behavior of calling directly efl_invalidate to be the
// same as efl_parent_set(NULL).
if (!obj->is_invalidating)
efl_parent_set(obj_id, NULL);
EO_OBJ_DONE(obj_id);
}
// Generate the invalidate event in all case and make sure it happens
// before any user code can change the children invalidate state. This
// make sure that the entire tree of object is valid at the time of
// the invalidate event.
void
_efl_invalidate(_Eo_Object *obj)
{
Eina_Array stash = { 0 };
Efl_Object_Data *pd;
_Eo_Object *child;
Eo *id;
if (obj->is_invalidating) return ;
obj->is_invalidating = EINA_TRUE;
if (obj->invalidate) return;
id = _eo_obj_id_get(obj);
pd = efl_data_scope_get(id, EFL_OBJECT_CLASS);
if (pd->event_cb_EFL_EVENT_INVALIDATE)
efl_event_callback_call(id, EFL_EVENT_INVALIDATE, NULL);
efl_invalidate(id);
eina_array_step_set(&stash, sizeof (stash), 4);
// Invalidate all children too
EINA_INLIST_FOREACH(pd->children, child)
eina_array_push(&stash, _efl_ref(child));
while ((child = eina_array_pop(&stash)))
{
Eo *child_id = _eo_obj_id_get(child);
efl_parent_set(child_id, NULL);
_efl_unref(child);
}
eina_array_flush(&stash);
obj->invalidate = EINA_TRUE;
}
static void _key_generic_cb_del(void *data, const Efl_Event *event);
2013-12-25 06:13:41 -08:00
static void
_eo_generic_data_node_free(Eo_Generic_Data_Node *node)
{
switch (node->d_type)
{
case DATA_PTR:
break;
case DATA_OBJ:
// FIXME: should this use "destruct" event instead?
efl_event_callback_del(node->d.obj, EFL_EVENT_DEL, _key_generic_cb_del, node);
efl_unref(node->d.obj);
break;
case DATA_OBJ_WEAK:
// FIXME: should this use "destruct" event instead?
efl_event_callback_del(node->d.obj, EFL_EVENT_DEL, _key_generic_cb_del, node);
break;
case DATA_VAL:
eina_value_free(node->d.val);
break;
}
2013-12-25 06:13:41 -08:00
eina_stringshare_del(node->key);
eina_freeq_ptr_main_add(node, free, sizeof(*node));
2013-12-25 06:13:41 -08:00
}
static void
_eo_generic_data_del_all(Eo *obj EINA_UNUSED, Efl_Object_Data *pd)
2013-12-25 06:13:41 -08:00
{
Eo_Generic_Data_Node *node;
Efl_Object_Extension *ext = pd->ext;
2013-12-25 06:13:41 -08:00
if (!ext) return;
while (ext->generic_data)
2013-12-25 06:13:41 -08:00
{
node = (Eo_Generic_Data_Node *)ext->generic_data;
ext->generic_data = eina_inlist_remove(ext->generic_data,
EINA_INLIST_GET(node));
2013-12-25 06:13:41 -08:00
_eo_generic_data_node_free(node);
}
}
static void
_eo_key_generic_direct_del(Efl_Object_Data *pd, Eo_Generic_Data_Node *node, Eina_Bool call_free)
{
Efl_Object_Extension *ext = pd->ext;
ext->generic_data = eina_inlist_remove
(ext->generic_data, EINA_INLIST_GET(node));
if (call_free) _eo_generic_data_node_free(node);
}
static void
_eo_key_generic_del(const Eo *obj EINA_UNUSED, Efl_Object_Data *pd, const char *key, Eina_Bool call_free)
{
Eo_Generic_Data_Node *node;
Efl_Object_Extension *ext = pd->ext;
EINA_INLIST_FOREACH(ext->generic_data, node)
{
if (!strcmp(node->key, key))
{
ext->generic_data = eina_inlist_remove
(ext->generic_data, EINA_INLIST_GET(node));
if (call_free) _eo_generic_data_node_free(node);
return;
}
}
}
/* Return TRUE if the object was newly added. */
static Eo_Generic_Data_Node *
_key_generic_set(const Eo *obj, Efl_Object_Data *pd, const char *key, const void *data, Eo_Generic_Data_Node_Type d_type, Eina_Bool call_free)
{
Eo_Generic_Data_Node *node;
Efl_Object_Extension *ext = pd->ext;
2013-12-25 06:13:41 -08:00
if (!key) return NULL;
if (ext)
2013-12-25 06:13:41 -08:00
{
if (!data)
{
_eo_key_generic_del(obj, pd, key, call_free);
return NULL;
}
EINA_INLIST_FOREACH(ext->generic_data, node)
2013-12-25 06:13:41 -08:00
{
if (!strcmp(node->key, key))
{
if ((node->d_type == d_type) && (node->d.ptr == data))
return NULL;
ext->generic_data = eina_inlist_remove
(ext->generic_data, EINA_INLIST_GET(node));
_eo_generic_data_node_free(node);
break;
}
2013-12-25 06:13:41 -08:00
}
}
ext = _efl_object_extension_need(pd);
if (ext)
{
node = calloc(1, sizeof(Eo_Generic_Data_Node));
if (!node) return NULL;
node->obj = obj;
node->key = eina_stringshare_add(key);
node->d.ptr = (void *) data;
node->d_type = d_type;
ext->generic_data = eina_inlist_prepend
(ext->generic_data, EINA_INLIST_GET(node));
return node;
}
return NULL;
}
static void *
_key_generic_get(const Eo *obj, Efl_Object_Data *pd, const char *key, Eo_Generic_Data_Node_Type d_type)
{
Eo_Generic_Data_Node *node;
Efl_Object_Extension *ext = pd->ext;
if (!key) return NULL;
if (!ext) return NULL;
EINA_INLIST_FOREACH(ext->generic_data, node)
{
if (node->key && !strcmp(node->key, key))
{
if (node->d_type == d_type)
{
ext->generic_data = eina_inlist_promote
(ext->generic_data, EINA_INLIST_GET(node));
return node->d.ptr;
}
else
{
ERR("Object %p key '%s' asked for %d but is %d'",
obj, key, d_type, node->d_type);
return NULL;
}
}
}
2013-12-25 06:13:41 -08:00
return NULL;
}
static void
_key_generic_cb_del(void *data, const Efl_Event *event EINA_UNUSED)
{
Eo_Generic_Data_Node *node = data;
Efl_Object_Data *pd = efl_data_scope_get(node->obj, EFL_OBJECT_CLASS);
_eo_key_generic_direct_del(pd, node, EINA_TRUE);
}
EOLIAN static void
_efl_object_key_data_set(Eo *obj, Efl_Object_Data *pd, const char *key, const void *data)
{
_key_generic_set(obj, pd, key, data, DATA_PTR, EINA_TRUE);
}
eo: Rename EAPI macro to EO_API in Eo library Summary: Patch from a series of patches to rename EAPI symbols to specific library DSOs. = The Rationale = This patch is from a series of patches to rename EAPI symbols to specific library DSOs. EAPI was designed to be able to pass `__attribute__ ((visibility ("default")))` for symbols with GCC, which would mean that even if -fvisibility=hidden was used when compiling the library, the needed symbols would get exported. MSVC __almost__ works like GCC (or mingw) in which you can declare everything as export and it will just work (slower, but it will work). But there's a caveat: global variables will not work the same way for MSVC, but works for mingw and GCC. For global variables (as opposed to functions), MSVC requires correct DSO visibility for MSVC: instead of declaring a symbol as export for everything, you need to declare it as import when importing from another DSO and export when defining it locally. With current EAPI definitions, we get the following example working in mingw and MSVC (observe it doesn't define any global variables as exported symbols). Example 1: dll1: ``` EAPI void foo(void); EAPI void bar() { foo(); } ``` dll2: ``` EAPI void foo() { printf ("foo\n"); } ``` This works fine with API defined as __declspec(dllexport) in both cases and for gcc defining as `__atttribute__((visibility("default")))`. However, the following: Example 2: dll1: ``` EAPI extern int foo; EAPI void foobar(void); EAPI void bar() { foo = 5; foobar(); } ``` dll2: ``` EAPI int foo = 0; EAPI void foobar() { printf ("foo %d\n", foo); } ``` This will work on mingw but will not work for MSVC. And that's why LIBAPI is the only solution that works for MSVC. Co-authored-by: João Paulo Taylor Ienczak Zanette <jpaulotiz@gmail.com> Co-authored-by: Lucas Cavalcante de Sousa <lucks.sousa@gmail.com> Co-authored-by: Ricardo Campos <ricardo.campos@expertise.dev> Reviewers: jptiz, lucas, vtorri, woohyun Reviewed By: jptiz, lucas, vtorri Subscribers: cedric, #reviewers, #committers Tags: #efl Differential Revision: https://phab.enlightenment.org/D12203
2020-12-09 08:50:29 -08:00
EO_API EFL_VOID_FUNC_BODYV(efl_key_data_set, EFL_FUNC_CALL(key, data),
2017-04-26 07:18:49 -07:00
const char *key, const void *data);
EOLIAN static void *
_efl_object_key_data_get(Eo *obj, Efl_Object_Data *pd, const char *key)
{
return _key_generic_get(obj, pd, key, DATA_PTR);
}
eo: Rename EAPI macro to EO_API in Eo library Summary: Patch from a series of patches to rename EAPI symbols to specific library DSOs. = The Rationale = This patch is from a series of patches to rename EAPI symbols to specific library DSOs. EAPI was designed to be able to pass `__attribute__ ((visibility ("default")))` for symbols with GCC, which would mean that even if -fvisibility=hidden was used when compiling the library, the needed symbols would get exported. MSVC __almost__ works like GCC (or mingw) in which you can declare everything as export and it will just work (slower, but it will work). But there's a caveat: global variables will not work the same way for MSVC, but works for mingw and GCC. For global variables (as opposed to functions), MSVC requires correct DSO visibility for MSVC: instead of declaring a symbol as export for everything, you need to declare it as import when importing from another DSO and export when defining it locally. With current EAPI definitions, we get the following example working in mingw and MSVC (observe it doesn't define any global variables as exported symbols). Example 1: dll1: ``` EAPI void foo(void); EAPI void bar() { foo(); } ``` dll2: ``` EAPI void foo() { printf ("foo\n"); } ``` This works fine with API defined as __declspec(dllexport) in both cases and for gcc defining as `__atttribute__((visibility("default")))`. However, the following: Example 2: dll1: ``` EAPI extern int foo; EAPI void foobar(void); EAPI void bar() { foo = 5; foobar(); } ``` dll2: ``` EAPI int foo = 0; EAPI void foobar() { printf ("foo %d\n", foo); } ``` This will work on mingw but will not work for MSVC. And that's why LIBAPI is the only solution that works for MSVC. Co-authored-by: João Paulo Taylor Ienczak Zanette <jpaulotiz@gmail.com> Co-authored-by: Lucas Cavalcante de Sousa <lucks.sousa@gmail.com> Co-authored-by: Ricardo Campos <ricardo.campos@expertise.dev> Reviewers: jptiz, lucas, vtorri, woohyun Reviewed By: jptiz, lucas, vtorri Subscribers: cedric, #reviewers, #committers Tags: #efl Differential Revision: https://phab.enlightenment.org/D12203
2020-12-09 08:50:29 -08:00
EO_API EFL_FUNC_BODYV_CONST(efl_key_data_get, void *, NULL, EFL_FUNC_CALL(key),
2017-04-26 07:18:49 -07:00
const char *key);
EOLIAN static void
_efl_object_key_ref_set(Eo *obj EINA_UNUSED, Efl_Object_Data *pd, const char *key, const Eo *objdata)
{
Eo_Generic_Data_Node *node;
eo - make eo id table TLS private data for thread safety and speed This moved all the eoid tables, eoid lookup caches, generation count information ad eo_isa cache into a TLS segment of memory that is thread private. There is also a shared domain for EO objects that all threads can access, but it has an added cost of a lock. This means objects accessed outside the thread they were created in cannot be accessed by another thread unless they are adopted in temporarily, or create4d with the shared domain active at the time of creation. child objects will use their parent object domain if created with a parent object passed in. If you were accessing EO (EFL) objects across threads before then this will actually now cause your code to fail as it was invalid before to do this as no actual objects were threadsafe in EFL, so this will force things to "fail early". ecore_thread_main_loop_begin() and end() still work as this uses the eo domain adoption features to temporarily adopt a domain during this section and then return it when done. This returns speed back to eo brining the overhead in my tests of lookup for the elm genlist autobounce test in elementary from about 5-7% down to 2.5-2.6%. A steep drop. This does not mean everything is perfect. Still to do are: 1. Tests in the test suite 2. Some API's to help for sending objects from thread to thread 3. Make the eo call cache TLS data to make it also safe 4. Look at other locks in eo and probably move them to TLS data 5. Make eo resolve and call wrappers that call the real method func do recursive mutex wrapping of the given object IF it is a shared object to provide threadsafety transparently for shared objects (but adding some overhead as a result) 6. Test test est, and that is why this commit is going in now for wider testing 7. Decide how to make this work with sending IPC (between threads) 8. Deciding what makes an object sendable (a sendable property in base?) 9. Deciding what makes an object shareable (a sharable property in base?)
2016-09-07 01:53:33 -07:00
if (!_eo_id_domain_compatible(obj, objdata)) return;
node = _key_generic_set(obj, pd, key, objdata, DATA_OBJ, EINA_TRUE);
if (node)
{
efl_ref(objdata);
efl_event_callback_add((Eo *)objdata, EFL_EVENT_DEL, _key_generic_cb_del, node);
}
}
eo: Rename EAPI macro to EO_API in Eo library Summary: Patch from a series of patches to rename EAPI symbols to specific library DSOs. = The Rationale = This patch is from a series of patches to rename EAPI symbols to specific library DSOs. EAPI was designed to be able to pass `__attribute__ ((visibility ("default")))` for symbols with GCC, which would mean that even if -fvisibility=hidden was used when compiling the library, the needed symbols would get exported. MSVC __almost__ works like GCC (or mingw) in which you can declare everything as export and it will just work (slower, but it will work). But there's a caveat: global variables will not work the same way for MSVC, but works for mingw and GCC. For global variables (as opposed to functions), MSVC requires correct DSO visibility for MSVC: instead of declaring a symbol as export for everything, you need to declare it as import when importing from another DSO and export when defining it locally. With current EAPI definitions, we get the following example working in mingw and MSVC (observe it doesn't define any global variables as exported symbols). Example 1: dll1: ``` EAPI void foo(void); EAPI void bar() { foo(); } ``` dll2: ``` EAPI void foo() { printf ("foo\n"); } ``` This works fine with API defined as __declspec(dllexport) in both cases and for gcc defining as `__atttribute__((visibility("default")))`. However, the following: Example 2: dll1: ``` EAPI extern int foo; EAPI void foobar(void); EAPI void bar() { foo = 5; foobar(); } ``` dll2: ``` EAPI int foo = 0; EAPI void foobar() { printf ("foo %d\n", foo); } ``` This will work on mingw but will not work for MSVC. And that's why LIBAPI is the only solution that works for MSVC. Co-authored-by: João Paulo Taylor Ienczak Zanette <jpaulotiz@gmail.com> Co-authored-by: Lucas Cavalcante de Sousa <lucks.sousa@gmail.com> Co-authored-by: Ricardo Campos <ricardo.campos@expertise.dev> Reviewers: jptiz, lucas, vtorri, woohyun Reviewed By: jptiz, lucas, vtorri Subscribers: cedric, #reviewers, #committers Tags: #efl Differential Revision: https://phab.enlightenment.org/D12203
2020-12-09 08:50:29 -08:00
EO_API EFL_VOID_FUNC_BODYV(efl_key_ref_set, EFL_FUNC_CALL(key, objdata),
2017-04-26 07:18:49 -07:00
const char *key, const Efl_Object *objdata);
EOLIAN static Eo *
_efl_object_key_ref_get(Eo *obj, Efl_Object_Data *pd, const char *key)
{
return _key_generic_get(obj, pd, key, DATA_OBJ);
}
eo: Rename EAPI macro to EO_API in Eo library Summary: Patch from a series of patches to rename EAPI symbols to specific library DSOs. = The Rationale = This patch is from a series of patches to rename EAPI symbols to specific library DSOs. EAPI was designed to be able to pass `__attribute__ ((visibility ("default")))` for symbols with GCC, which would mean that even if -fvisibility=hidden was used when compiling the library, the needed symbols would get exported. MSVC __almost__ works like GCC (or mingw) in which you can declare everything as export and it will just work (slower, but it will work). But there's a caveat: global variables will not work the same way for MSVC, but works for mingw and GCC. For global variables (as opposed to functions), MSVC requires correct DSO visibility for MSVC: instead of declaring a symbol as export for everything, you need to declare it as import when importing from another DSO and export when defining it locally. With current EAPI definitions, we get the following example working in mingw and MSVC (observe it doesn't define any global variables as exported symbols). Example 1: dll1: ``` EAPI void foo(void); EAPI void bar() { foo(); } ``` dll2: ``` EAPI void foo() { printf ("foo\n"); } ``` This works fine with API defined as __declspec(dllexport) in both cases and for gcc defining as `__atttribute__((visibility("default")))`. However, the following: Example 2: dll1: ``` EAPI extern int foo; EAPI void foobar(void); EAPI void bar() { foo = 5; foobar(); } ``` dll2: ``` EAPI int foo = 0; EAPI void foobar() { printf ("foo %d\n", foo); } ``` This will work on mingw but will not work for MSVC. And that's why LIBAPI is the only solution that works for MSVC. Co-authored-by: João Paulo Taylor Ienczak Zanette <jpaulotiz@gmail.com> Co-authored-by: Lucas Cavalcante de Sousa <lucks.sousa@gmail.com> Co-authored-by: Ricardo Campos <ricardo.campos@expertise.dev> Reviewers: jptiz, lucas, vtorri, woohyun Reviewed By: jptiz, lucas, vtorri Subscribers: cedric, #reviewers, #committers Tags: #efl Differential Revision: https://phab.enlightenment.org/D12203
2020-12-09 08:50:29 -08:00
EO_API EFL_FUNC_BODYV_CONST(efl_key_ref_get, Efl_Object *, NULL,
2017-04-26 07:18:49 -07:00
EFL_FUNC_CALL(key), const char *key);
EOLIAN static void
_efl_object_key_wref_set(Eo *obj, Efl_Object_Data *pd, const char * key, const Efl_Object *objdata)
{
Eo_Generic_Data_Node *node;
eo - make eo id table TLS private data for thread safety and speed This moved all the eoid tables, eoid lookup caches, generation count information ad eo_isa cache into a TLS segment of memory that is thread private. There is also a shared domain for EO objects that all threads can access, but it has an added cost of a lock. This means objects accessed outside the thread they were created in cannot be accessed by another thread unless they are adopted in temporarily, or create4d with the shared domain active at the time of creation. child objects will use their parent object domain if created with a parent object passed in. If you were accessing EO (EFL) objects across threads before then this will actually now cause your code to fail as it was invalid before to do this as no actual objects were threadsafe in EFL, so this will force things to "fail early". ecore_thread_main_loop_begin() and end() still work as this uses the eo domain adoption features to temporarily adopt a domain during this section and then return it when done. This returns speed back to eo brining the overhead in my tests of lookup for the elm genlist autobounce test in elementary from about 5-7% down to 2.5-2.6%. A steep drop. This does not mean everything is perfect. Still to do are: 1. Tests in the test suite 2. Some API's to help for sending objects from thread to thread 3. Make the eo call cache TLS data to make it also safe 4. Look at other locks in eo and probably move them to TLS data 5. Make eo resolve and call wrappers that call the real method func do recursive mutex wrapping of the given object IF it is a shared object to provide threadsafety transparently for shared objects (but adding some overhead as a result) 6. Test test est, and that is why this commit is going in now for wider testing 7. Decide how to make this work with sending IPC (between threads) 8. Deciding what makes an object sendable (a sendable property in base?) 9. Deciding what makes an object shareable (a sharable property in base?)
2016-09-07 01:53:33 -07:00
if (!_eo_id_domain_compatible(obj, objdata)) return;
node = _key_generic_set(obj, pd, key, objdata, DATA_OBJ_WEAK, EINA_TRUE);
if (node)
{
efl_event_callback_add((Eo *)objdata, EFL_EVENT_DEL, _key_generic_cb_del, node);
}
}
eo: Rename EAPI macro to EO_API in Eo library Summary: Patch from a series of patches to rename EAPI symbols to specific library DSOs. = The Rationale = This patch is from a series of patches to rename EAPI symbols to specific library DSOs. EAPI was designed to be able to pass `__attribute__ ((visibility ("default")))` for symbols with GCC, which would mean that even if -fvisibility=hidden was used when compiling the library, the needed symbols would get exported. MSVC __almost__ works like GCC (or mingw) in which you can declare everything as export and it will just work (slower, but it will work). But there's a caveat: global variables will not work the same way for MSVC, but works for mingw and GCC. For global variables (as opposed to functions), MSVC requires correct DSO visibility for MSVC: instead of declaring a symbol as export for everything, you need to declare it as import when importing from another DSO and export when defining it locally. With current EAPI definitions, we get the following example working in mingw and MSVC (observe it doesn't define any global variables as exported symbols). Example 1: dll1: ``` EAPI void foo(void); EAPI void bar() { foo(); } ``` dll2: ``` EAPI void foo() { printf ("foo\n"); } ``` This works fine with API defined as __declspec(dllexport) in both cases and for gcc defining as `__atttribute__((visibility("default")))`. However, the following: Example 2: dll1: ``` EAPI extern int foo; EAPI void foobar(void); EAPI void bar() { foo = 5; foobar(); } ``` dll2: ``` EAPI int foo = 0; EAPI void foobar() { printf ("foo %d\n", foo); } ``` This will work on mingw but will not work for MSVC. And that's why LIBAPI is the only solution that works for MSVC. Co-authored-by: João Paulo Taylor Ienczak Zanette <jpaulotiz@gmail.com> Co-authored-by: Lucas Cavalcante de Sousa <lucks.sousa@gmail.com> Co-authored-by: Ricardo Campos <ricardo.campos@expertise.dev> Reviewers: jptiz, lucas, vtorri, woohyun Reviewed By: jptiz, lucas, vtorri Subscribers: cedric, #reviewers, #committers Tags: #efl Differential Revision: https://phab.enlightenment.org/D12203
2020-12-09 08:50:29 -08:00
EO_API EFL_VOID_FUNC_BODYV(efl_key_wref_set, EFL_FUNC_CALL(key, objdata),
2017-04-26 07:18:49 -07:00
const char *key, const Efl_Object *objdata);
EOLIAN static Eo *
_efl_object_key_wref_get(Eo *obj, Efl_Object_Data *pd, const char * key)
{
return _key_generic_get(obj, pd, key, DATA_OBJ_WEAK);
}
eo: Rename EAPI macro to EO_API in Eo library Summary: Patch from a series of patches to rename EAPI symbols to specific library DSOs. = The Rationale = This patch is from a series of patches to rename EAPI symbols to specific library DSOs. EAPI was designed to be able to pass `__attribute__ ((visibility ("default")))` for symbols with GCC, which would mean that even if -fvisibility=hidden was used when compiling the library, the needed symbols would get exported. MSVC __almost__ works like GCC (or mingw) in which you can declare everything as export and it will just work (slower, but it will work). But there's a caveat: global variables will not work the same way for MSVC, but works for mingw and GCC. For global variables (as opposed to functions), MSVC requires correct DSO visibility for MSVC: instead of declaring a symbol as export for everything, you need to declare it as import when importing from another DSO and export when defining it locally. With current EAPI definitions, we get the following example working in mingw and MSVC (observe it doesn't define any global variables as exported symbols). Example 1: dll1: ``` EAPI void foo(void); EAPI void bar() { foo(); } ``` dll2: ``` EAPI void foo() { printf ("foo\n"); } ``` This works fine with API defined as __declspec(dllexport) in both cases and for gcc defining as `__atttribute__((visibility("default")))`. However, the following: Example 2: dll1: ``` EAPI extern int foo; EAPI void foobar(void); EAPI void bar() { foo = 5; foobar(); } ``` dll2: ``` EAPI int foo = 0; EAPI void foobar() { printf ("foo %d\n", foo); } ``` This will work on mingw but will not work for MSVC. And that's why LIBAPI is the only solution that works for MSVC. Co-authored-by: João Paulo Taylor Ienczak Zanette <jpaulotiz@gmail.com> Co-authored-by: Lucas Cavalcante de Sousa <lucks.sousa@gmail.com> Co-authored-by: Ricardo Campos <ricardo.campos@expertise.dev> Reviewers: jptiz, lucas, vtorri, woohyun Reviewed By: jptiz, lucas, vtorri Subscribers: cedric, #reviewers, #committers Tags: #efl Differential Revision: https://phab.enlightenment.org/D12203
2020-12-09 08:50:29 -08:00
EO_API EFL_FUNC_BODYV_CONST(efl_key_wref_get, Efl_Object *, NULL,
2017-04-26 07:18:49 -07:00
EFL_FUNC_CALL(key), const char *key);
EOLIAN static void
_efl_object_key_value_set(Eo *obj EINA_UNUSED, Efl_Object_Data *pd, const char *key, Eina_Value *value)
{
_key_generic_set(obj, pd, key, value, DATA_VAL, EINA_TRUE);
}
eo: Rename EAPI macro to EO_API in Eo library Summary: Patch from a series of patches to rename EAPI symbols to specific library DSOs. = The Rationale = This patch is from a series of patches to rename EAPI symbols to specific library DSOs. EAPI was designed to be able to pass `__attribute__ ((visibility ("default")))` for symbols with GCC, which would mean that even if -fvisibility=hidden was used when compiling the library, the needed symbols would get exported. MSVC __almost__ works like GCC (or mingw) in which you can declare everything as export and it will just work (slower, but it will work). But there's a caveat: global variables will not work the same way for MSVC, but works for mingw and GCC. For global variables (as opposed to functions), MSVC requires correct DSO visibility for MSVC: instead of declaring a symbol as export for everything, you need to declare it as import when importing from another DSO and export when defining it locally. With current EAPI definitions, we get the following example working in mingw and MSVC (observe it doesn't define any global variables as exported symbols). Example 1: dll1: ``` EAPI void foo(void); EAPI void bar() { foo(); } ``` dll2: ``` EAPI void foo() { printf ("foo\n"); } ``` This works fine with API defined as __declspec(dllexport) in both cases and for gcc defining as `__atttribute__((visibility("default")))`. However, the following: Example 2: dll1: ``` EAPI extern int foo; EAPI void foobar(void); EAPI void bar() { foo = 5; foobar(); } ``` dll2: ``` EAPI int foo = 0; EAPI void foobar() { printf ("foo %d\n", foo); } ``` This will work on mingw but will not work for MSVC. And that's why LIBAPI is the only solution that works for MSVC. Co-authored-by: João Paulo Taylor Ienczak Zanette <jpaulotiz@gmail.com> Co-authored-by: Lucas Cavalcante de Sousa <lucks.sousa@gmail.com> Co-authored-by: Ricardo Campos <ricardo.campos@expertise.dev> Reviewers: jptiz, lucas, vtorri, woohyun Reviewed By: jptiz, lucas, vtorri Subscribers: cedric, #reviewers, #committers Tags: #efl Differential Revision: https://phab.enlightenment.org/D12203
2020-12-09 08:50:29 -08:00
EO_API EFL_VOID_FUNC_BODYV(efl_key_value_set, EFL_FUNC_CALL(key, value),
2017-04-26 07:18:49 -07:00
const char *key, Eina_Value *value);
EOLIAN static Eina_Value *
_efl_object_key_value_get(Eo *obj, Efl_Object_Data *pd, const char *key)
{
return _key_generic_get(obj, pd, key, DATA_VAL);
}
eo: Rename EAPI macro to EO_API in Eo library Summary: Patch from a series of patches to rename EAPI symbols to specific library DSOs. = The Rationale = This patch is from a series of patches to rename EAPI symbols to specific library DSOs. EAPI was designed to be able to pass `__attribute__ ((visibility ("default")))` for symbols with GCC, which would mean that even if -fvisibility=hidden was used when compiling the library, the needed symbols would get exported. MSVC __almost__ works like GCC (or mingw) in which you can declare everything as export and it will just work (slower, but it will work). But there's a caveat: global variables will not work the same way for MSVC, but works for mingw and GCC. For global variables (as opposed to functions), MSVC requires correct DSO visibility for MSVC: instead of declaring a symbol as export for everything, you need to declare it as import when importing from another DSO and export when defining it locally. With current EAPI definitions, we get the following example working in mingw and MSVC (observe it doesn't define any global variables as exported symbols). Example 1: dll1: ``` EAPI void foo(void); EAPI void bar() { foo(); } ``` dll2: ``` EAPI void foo() { printf ("foo\n"); } ``` This works fine with API defined as __declspec(dllexport) in both cases and for gcc defining as `__atttribute__((visibility("default")))`. However, the following: Example 2: dll1: ``` EAPI extern int foo; EAPI void foobar(void); EAPI void bar() { foo = 5; foobar(); } ``` dll2: ``` EAPI int foo = 0; EAPI void foobar() { printf ("foo %d\n", foo); } ``` This will work on mingw but will not work for MSVC. And that's why LIBAPI is the only solution that works for MSVC. Co-authored-by: João Paulo Taylor Ienczak Zanette <jpaulotiz@gmail.com> Co-authored-by: Lucas Cavalcante de Sousa <lucks.sousa@gmail.com> Co-authored-by: Ricardo Campos <ricardo.campos@expertise.dev> Reviewers: jptiz, lucas, vtorri, woohyun Reviewed By: jptiz, lucas, vtorri Subscribers: cedric, #reviewers, #committers Tags: #efl Differential Revision: https://phab.enlightenment.org/D12203
2020-12-09 08:50:29 -08:00
EO_API EFL_FUNC_BODYV_CONST(efl_key_value_get, Eina_Value *, NULL,
2017-04-26 07:18:49 -07:00
EFL_FUNC_CALL(key), const char *key);
EOLIAN static void
_efl_object_name_set(Eo *obj EINA_UNUSED, Efl_Object_Data *pd, const char *name)
{
if ((name) && (!name[0])) name = NULL;
if (name)
{
_efl_object_extension_need(pd);
if (pd->ext) eina_stringshare_replace(&(pd->ext->name), name);
}
else
{
if (!pd->ext) return;
if (pd->ext->name)
{
eina_stringshare_replace(&(pd->ext->name), name);
_efl_object_extension_noneed(pd);
}
}
}
EOLIAN static const char *
_efl_object_name_get(const Eo *obj EINA_UNUSED, Efl_Object_Data *pd)
{
if (!pd->ext) return NULL;
return pd->ext->name;
}
static inline Eina_Bool
_name_match(const char *match, Eina_Bool is_glob, const char *str)
{
if (str)
{
if (is_glob)
{
// if match string is empty - then it matches - same as "*"
if (!match[0]) return EINA_TRUE;
// if match string is "*" special case it and match
if ((match[0] == '*') && (match[1] == 0)) return EINA_TRUE;
// actual compare
if (!fnmatch(match, str, 0)) return EINA_TRUE;
}
else
{
// if match string is empty - then it matches - same as "*"
if (!match[0]) return EINA_TRUE;
// if pointers are the same they must be the same
if (match == str) return EINA_TRUE;
// actual compare
if (!strcmp(match, str)) return EINA_TRUE;
}
}
return EINA_FALSE;
}
static inline Eina_Bool
_matchall(const char *match)
{
if ((match[0] == 0) || ((match[0] == '*') && (match[1] == 0)))
return EINA_TRUE;
return EINA_FALSE;
}
static Eina_Bool
_hasglob(const char *match)
{
if (strpbrk(match, "*?[")) return EINA_TRUE;
return EINA_FALSE;
}
static Eina_Bool
_ismultiglob(const char *match)
{
if ((match[0] == '*') && (match[1] == '*') && (match[2] == 0))
return EINA_TRUE;
if ((match[0] == '*') && (match[1] == '*') && (match[2] == '/'))
return EINA_TRUE;
if ((match[0] == '/') && (match[1] == '*') && (match[2] == '*') && (match[3] == 0))
return EINA_TRUE;
if ((match[0] == '/') && (match[1] == '*') && (match[2] == '*') && (match[3] == '/'))
return EINA_TRUE;
return EINA_FALSE;
}
EOLIAN static Efl_Object *
_efl_object_name_find(const Eo *obj EINA_UNUSED, Efl_Object_Data *pd, const char *search)
{
Eo *child;
_Eo_Object *child_eo;
const char *name, *p, *klass_name;
// notes:
// if search contains NO "/" char, then its just a name search.
// if there is one or more "/" chars, then these are explicitly object
// delimiters.
// a name of "**" means 0 or more objects in the heirachy chain
// if the string has no "/" char at the start, it implies "/**/"
// a name can be a name or the form "class:name" where the object must
// be of class named "class" and name "name". if "name" is empty like:
// "class:" then an object of any name will match like "class:*". an
// empty class like ":name" is the sanme as "*:name" which is the same
// as "name". class ane name of course can be basic globs but not **
// search string NULL or "" is invalid
if (!search) return NULL;
if (!search[0]) return NULL;
if (strchr(search, '/'))
{
ERR("Looking up object by path '%s' is not supported", search);
return NULL;
}
else
{
// if this is a multi glob - "**" then we don't have a name or
// class to match at all so just don't look
if (_ismultiglob(search)) return NULL;
// check if this is "class:name" or just "name"
if ((p = strchr(search, ':')))
{
// "class:name"
char *klass;
char *search_name;
size_t colon_location = p - search;
Eina_Bool klass_glob = EINA_FALSE;
Eina_Bool name_glob = EINA_FALSE;
// split class:name into 2 strings dropping :
klass = alloca(strlen(search) + 1);
strcpy(klass, search);
klass[colon_location] = '\0';
search_name = klass + colon_location + 1;
// figure out if class or name are globs
klass_glob = _hasglob(klass);
name_glob = _hasglob(search_name);
EINA_INLIST_FOREACH(pd->children, child_eo)
{
child = _eo_obj_id_get(child_eo);
name = efl_name_get(child);
klass_name = efl_class_name_get(efl_class_get(child));
if (_name_match(klass, klass_glob, klass_name) &&
(((!_matchall(klass)) && (!name) && (_matchall(search_name))) ||
((name) && _name_match(search_name, name_glob, name))))
return child;
child = efl_name_find(child, search);
if (child) return child;
}
}
else
{
if (_hasglob(search))
{
// we have a glob - fnmatch
EINA_INLIST_FOREACH(pd->children, child_eo)
{
child = _eo_obj_id_get(child_eo);
name = efl_name_get(child);
if ((name) && (_name_match(search, EINA_TRUE, name)))
return child;
child = efl_name_find(child, search);
if (child) return child;
}
}
else
{
// fast path for simple "name"
EINA_INLIST_FOREACH(pd->children, child_eo)
{
child = _eo_obj_id_get(child_eo);
name = efl_name_get(child);
if ((name) && (_name_match(search, EINA_FALSE, name)))
return child;
child = efl_name_find(child, search);
if (child) return child;
}
}
}
}
return NULL;
}
EOLIAN static void
_efl_object_comment_set(Eo *obj EINA_UNUSED, Efl_Object_Data *pd, const char *comment)
{
if ((comment) && (!comment[0])) comment = NULL;
if (comment)
{
_efl_object_extension_need(pd);
if (pd->ext) eina_stringshare_replace(&(pd->ext->comment), comment);
}
else
{
if (!pd->ext) return;
if (pd->ext->comment)
{
eina_stringshare_replace(&(pd->ext->comment), comment);
_efl_object_extension_noneed(pd);
}
}
}
EOLIAN static const char *
_efl_object_comment_get(const Eo *obj EINA_UNUSED, Efl_Object_Data *pd)
{
if (!pd->ext) return NULL;
return pd->ext->comment;
}
EOLIAN static void
_efl_object_debug_name_override(Eo *obj_id EINA_UNUSED, Efl_Object_Data *pd EINA_UNUSED, Eina_Strbuf *sb EINA_UNUSED)
{
}
eo: Rename EAPI macro to EO_API in Eo library Summary: Patch from a series of patches to rename EAPI symbols to specific library DSOs. = The Rationale = This patch is from a series of patches to rename EAPI symbols to specific library DSOs. EAPI was designed to be able to pass `__attribute__ ((visibility ("default")))` for symbols with GCC, which would mean that even if -fvisibility=hidden was used when compiling the library, the needed symbols would get exported. MSVC __almost__ works like GCC (or mingw) in which you can declare everything as export and it will just work (slower, but it will work). But there's a caveat: global variables will not work the same way for MSVC, but works for mingw and GCC. For global variables (as opposed to functions), MSVC requires correct DSO visibility for MSVC: instead of declaring a symbol as export for everything, you need to declare it as import when importing from another DSO and export when defining it locally. With current EAPI definitions, we get the following example working in mingw and MSVC (observe it doesn't define any global variables as exported symbols). Example 1: dll1: ``` EAPI void foo(void); EAPI void bar() { foo(); } ``` dll2: ``` EAPI void foo() { printf ("foo\n"); } ``` This works fine with API defined as __declspec(dllexport) in both cases and for gcc defining as `__atttribute__((visibility("default")))`. However, the following: Example 2: dll1: ``` EAPI extern int foo; EAPI void foobar(void); EAPI void bar() { foo = 5; foobar(); } ``` dll2: ``` EAPI int foo = 0; EAPI void foobar() { printf ("foo %d\n", foo); } ``` This will work on mingw but will not work for MSVC. And that's why LIBAPI is the only solution that works for MSVC. Co-authored-by: João Paulo Taylor Ienczak Zanette <jpaulotiz@gmail.com> Co-authored-by: Lucas Cavalcante de Sousa <lucks.sousa@gmail.com> Co-authored-by: Ricardo Campos <ricardo.campos@expertise.dev> Reviewers: jptiz, lucas, vtorri, woohyun Reviewed By: jptiz, lucas, vtorri Subscribers: cedric, #reviewers, #committers Tags: #efl Differential Revision: https://phab.enlightenment.org/D12203
2020-12-09 08:50:29 -08:00
EO_API void
efl_del(const Eo *obj)
{
if (!obj) return ;
EO_OBJ_POINTER_RETURN(obj, oid);
_efl_ref(oid);
if (efl_parent_get((Eo *) obj))
{
efl_parent_set((Eo *) obj, NULL);
}
else
{
ERR("Calling efl_del on object %s with no parent is not advised any more.", efl_debug_name_get(obj));
efl_unref(obj);
}
_efl_unref(oid);
EO_OBJ_DONE(obj);
}
void
_efl_object_reuse(_Eo_Object *obj)
{
obj->is_invalidating = EINA_FALSE;
obj->invalidate = EINA_FALSE;
}
EOLIAN void
_efl_object_parent_set(Eo *obj, Efl_Object_Data *pd, Eo *parent_id)
{
2016-10-21 07:02:27 -07:00
Eo *prev_parent = pd->parent;
Eina_Bool bad_parent = EINA_FALSE;
if ((pd->parent == parent_id) ||
((parent_id) && (!_eo_id_domain_compatible(parent_id, obj))))
return;
if (parent_id != NULL)
{
EO_OBJ_POINTER_GOTO(parent_id, parent_obj, err_impossible);
bad_parent = parent_obj->invalidate || (obj == parent_id);
EO_OBJ_DONE(parent_id);
}
if (bad_parent) goto err_parent;
EO_OBJ_POINTER_GOTO(obj, eo_obj, err_impossible);
// Invalidated object can not be bring back to life
if (eo_obj->invalidate)
{
ERR("Call of efl_parent_set(%p, %p) when object of clas '%s' is already invalidated.\n", obj, parent_id, efl_class_name_get(obj));
goto err_impossible;
}
if (!parent_id)
{
if (prev_parent) _efl_invalidate(eo_obj);
}
if (pd->parent)
{
Efl_Object_Data *old_parent_pd = efl_data_scope_get(pd->parent,
EFL_OBJECT_CLASS);
if (old_parent_pd)
old_parent_pd->children = eina_inlist_remove(old_parent_pd->children,
EINA_INLIST_GET(eo_obj));
// this error is highly unlikely so move it out of the normal
// instruction path to avoid l1 cache pollution
else goto err_impossible;
}
/* Set new parent */
if (parent_id)
{
Efl_Object_Data *parent_pd = efl_data_scope_get(parent_id,
EFL_OBJECT_CLASS);
if (EINA_LIKELY(parent_pd != NULL))
{
pd->parent = parent_id;
parent_pd->children = eina_inlist_append(parent_pd->children,
EINA_INLIST_GET(eo_obj));
if (!prev_parent) efl_ref(obj);
}
else
{
pd->parent = NULL;
2016-10-21 07:02:27 -07:00
if (prev_parent) efl_unref(obj);
// unlikely this error happens, so move it out of execution path
// to improve l1 cache efficiency
goto err_parent_done;
}
eo_obj->parent = EINA_TRUE;
}
2016-10-21 07:02:27 -07:00
else
{
pd->parent = NULL;
eo_obj->parent = EINA_FALSE;
2016-10-21 07:02:27 -07:00
if (prev_parent && !eo_obj->del_triggered) efl_unref(obj);
}
EO_OBJ_DONE(obj);
return;
err_parent_done:
EO_OBJ_DONE(obj);
err_parent:
if (obj == parent_id)
ERR("New parent %p for object %p will not be set: THIS IS THE SAME OBJECT.",
parent_id, obj);
else
ERR("New parent %p for object %p is not a valid Eo object.",
parent_id, obj);
return;
err_impossible:
ERR("CONTACT DEVS!!! SHOULD NEVER HAPPEN!!! Old parent %p for object %p is not a valid Eo object.",
pd->parent, obj);
}
EOLIAN static Eo *
_efl_object_parent_get(const Eo *obj EINA_UNUSED, Efl_Object_Data *pd)
{
return pd->parent;
}
EOLIAN static Eina_Bool
_efl_object_finalized_get(const Eo *obj_id, Efl_Object_Data *pd EINA_UNUSED)
{
Eina_Bool finalized;
EO_OBJ_POINTER_RETURN_VAL(obj_id, obj, EINA_FALSE);
finalized = obj->finalized;
EO_OBJ_DONE(obj_id);
return finalized;
}
EOLIAN static Eina_Bool
_efl_object_invalidated_get(const Eo *obj_id, Efl_Object_Data *pd)
{
Eina_Bool invalidate;
EO_OBJ_POINTER_RETURN_VAL(obj_id, obj, EINA_TRUE);
invalidate = obj->invalidate;
EO_OBJ_DONE(obj_id);
if (!invalidate && pd && pd->parent)
return efl_invalidated_get(pd->parent);
return invalidate;
}
EOLIAN static Eina_Bool
_efl_object_invalidating_get(const Eo *obj_id, Efl_Object_Data *pd EINA_UNUSED)
{
Eina_Bool invalidating;
EO_OBJ_POINTER_RETURN_VAL(obj_id, obj, EINA_TRUE);
invalidating = obj->is_invalidating;
EO_OBJ_DONE(obj_id);
return invalidating;
}
EOLIAN static Efl_Object *
_efl_object_provider_find(const Eo *obj, Efl_Object_Data *pd, const Efl_Object *klass)
{
Eina_Bool invalidate;
Efl_Object *r = NULL;
invalidate = _efl_object_invalidated_get((Eo*) obj, NULL);
if (invalidate)
{
ERR("Calling efl_provider_find(%p) after the object was invalidated.", obj);
return NULL;
}
if (efl_isa(obj, klass)) return (Eo *) obj;
if (pd->ext) r = eina_hash_find(pd->ext->providers, &klass);
if (r) return r;
if (pd->parent) return efl_provider_find(pd->parent, klass);
return NULL;
}
static Eina_Bool
_efl_object_provider_register(Eo *obj EINA_UNUSED, Efl_Object_Data *pd, const Efl_Class *klass, const Efl_Object *provider)
{
// The passed object does not provide that said class.
if (!efl_isa(provider, klass)) return EINA_FALSE;
_efl_object_extension_need(pd);
if (!pd->ext) return EINA_FALSE;
if (!pd->ext->providers) pd->ext->providers = eina_hash_pointer_new(EINA_FREE_CB(efl_unref));
// Prevent double insertion for the same class
if (eina_hash_find(pd->ext->providers, &klass)) return EINA_FALSE;
// Note: I would prefer to use efl_xref here, but I can't figure a nice way to
// call efl_xunref on hash destruction.
return eina_hash_add(pd->ext->providers, &klass, efl_ref(provider));
}
static Eina_Bool
_efl_object_provider_unregister(Eo *obj EINA_UNUSED, Efl_Object_Data *pd, const Efl_Class *klass, const Efl_Object *provider)
{
Eina_Bool r;
if (!pd->ext) return EINA_FALSE;
r = eina_hash_del(pd->ext->providers, &klass, provider);
if (eina_hash_population(pd->ext->providers) != 0) return r;
eina_hash_free(pd->ext->providers);
pd->ext->providers = NULL;
_efl_object_extension_noneed(pd);
return r;
}
/* Children accessor */
typedef struct _Eo_Children_Iterator Eo_Children_Iterator;
struct _Eo_Children_Iterator
{
Eina_Iterator iterator;
Eina_Inlist *current;
_Eo_Object *obj;
Eo *obj_id;
};
static Eina_Bool
_efl_children_iterator_next(Eo_Children_Iterator *it, void **data)
{
if (!it->current) return EINA_FALSE;
if (data)
{
_Eo_Object *eo_obj = EINA_INLIST_CONTAINER_GET(it->current, _Eo_Object);
*data = _eo_obj_id_get(eo_obj);
}
it->current = it->current->next;
return EINA_TRUE;
}
static Eo *
_efl_children_iterator_container(Eo_Children_Iterator *it)
{
return it->obj_id;
}
static void
_efl_children_iterator_free(Eo_Children_Iterator *it)
{
_Efl_Class *klass;
_Eo_Object *obj;
klass = (_Efl_Class*) it->obj->klass;
obj = it->obj;
eina_spinlock_take(&klass->iterators.trash_lock);
if (klass->iterators.trash_count < 8)
{
klass->iterators.trash_count++;
eina_trash_push(&klass->iterators.trash, it);
}
else
{
eina_freeq_ptr_main_add(it, free, sizeof(*it));
}
eina_spinlock_release(&klass->iterators.trash_lock);
_efl_unref(obj);
}
EOLIAN static Eina_Iterator *
_efl_object_children_iterator_new(Eo *obj_id, Efl_Object_Data *pd)
{
_Efl_Class *klass;
Eo_Children_Iterator *it = NULL;
EO_OBJ_POINTER_RETURN_VAL(obj_id, obj, NULL);
if (pd->children)
{
klass = (_Efl_Class *)obj->klass;
eina_spinlock_take(&klass->iterators.trash_lock);
it = eina_trash_pop(&klass->iterators.trash);
if (it)
{
klass->iterators.trash_count--;
memset(it, 0, sizeof (Eo_Children_Iterator));
}
else it = calloc(1, sizeof (Eo_Children_Iterator));
eina_spinlock_release(&klass->iterators.trash_lock);
// very unlikely to not allocate the iterator to move this error
// handling out of l1 instruction cache
if (!it) goto done;
EINA_MAGIC_SET(&it->iterator, EINA_MAGIC_ITERATOR);
it->current = pd->children;
it->obj = _efl_ref(obj);
it->obj_id = obj_id;
it->iterator.next = FUNC_ITERATOR_NEXT(_efl_children_iterator_next);
it->iterator.get_container = FUNC_ITERATOR_GET_CONTAINER(_efl_children_iterator_container);
it->iterator.free = FUNC_ITERATOR_FREE(_efl_children_iterator_free);
}
done:
EO_OBJ_DONE(obj_id);
return (Eina_Iterator *)it;
}
EOLIAN static void
_efl_object_dbg_info_get(Eo *obj EINA_UNUSED, Efl_Object_Data *pd EINA_UNUSED, Efl_Dbg_Info *root_node EINA_UNUSED)
2013-12-25 06:13:41 -08:00
{ /* No info required in the meantime */
return;
}
eo: Rename EAPI macro to EO_API in Eo library Summary: Patch from a series of patches to rename EAPI symbols to specific library DSOs. = The Rationale = This patch is from a series of patches to rename EAPI symbols to specific library DSOs. EAPI was designed to be able to pass `__attribute__ ((visibility ("default")))` for symbols with GCC, which would mean that even if -fvisibility=hidden was used when compiling the library, the needed symbols would get exported. MSVC __almost__ works like GCC (or mingw) in which you can declare everything as export and it will just work (slower, but it will work). But there's a caveat: global variables will not work the same way for MSVC, but works for mingw and GCC. For global variables (as opposed to functions), MSVC requires correct DSO visibility for MSVC: instead of declaring a symbol as export for everything, you need to declare it as import when importing from another DSO and export when defining it locally. With current EAPI definitions, we get the following example working in mingw and MSVC (observe it doesn't define any global variables as exported symbols). Example 1: dll1: ``` EAPI void foo(void); EAPI void bar() { foo(); } ``` dll2: ``` EAPI void foo() { printf ("foo\n"); } ``` This works fine with API defined as __declspec(dllexport) in both cases and for gcc defining as `__atttribute__((visibility("default")))`. However, the following: Example 2: dll1: ``` EAPI extern int foo; EAPI void foobar(void); EAPI void bar() { foo = 5; foobar(); } ``` dll2: ``` EAPI int foo = 0; EAPI void foobar() { printf ("foo %d\n", foo); } ``` This will work on mingw but will not work for MSVC. And that's why LIBAPI is the only solution that works for MSVC. Co-authored-by: João Paulo Taylor Ienczak Zanette <jpaulotiz@gmail.com> Co-authored-by: Lucas Cavalcante de Sousa <lucks.sousa@gmail.com> Co-authored-by: Ricardo Campos <ricardo.campos@expertise.dev> Reviewers: jptiz, lucas, vtorri, woohyun Reviewed By: jptiz, lucas, vtorri Subscribers: cedric, #reviewers, #committers Tags: #efl Differential Revision: https://phab.enlightenment.org/D12203
2020-12-09 08:50:29 -08:00
EO_API EFL_VOID_FUNC_BODYV(efl_dbg_info_get, EFL_FUNC_CALL(root_node), Efl_Dbg_Info *root_node);
2013-12-25 06:13:41 -08:00
/* Weak reference. */
static inline size_t
_wref_count(Efl_Object_Data *pd)
2013-12-25 06:13:41 -08:00
{
Eo ***itr;
2013-12-25 06:13:41 -08:00
size_t count = 0;
Efl_Object_Extension *ext = pd->ext;
2013-12-25 06:13:41 -08:00
if ((!ext) || (!ext->wrefs)) return 0;
for (itr = ext->wrefs; *itr; itr++) count++;
2013-12-25 06:13:41 -08:00
return count;
}
EOLIAN static void
_efl_object_wref_add(Eo *obj, Efl_Object_Data *pd, Eo **wref)
2013-12-25 06:13:41 -08:00
{
size_t count;
Eo ***tmp;
Efl_Object_Extension *ext;
2013-12-25 06:13:41 -08:00
count = _wref_count(pd);
count += 1; /* New wref. */
ext = _efl_object_extension_need(pd);
if (ext)
{
tmp = realloc(ext->wrefs, sizeof(*ext->wrefs) * (count + 1));
if (tmp)
{
ext->wrefs = tmp;
ext->wrefs[count - 1] = wref;
ext->wrefs[count] = NULL;
*wref = obj;
}
}
2013-12-25 06:13:41 -08:00
}
eo: Rename EAPI macro to EO_API in Eo library Summary: Patch from a series of patches to rename EAPI symbols to specific library DSOs. = The Rationale = This patch is from a series of patches to rename EAPI symbols to specific library DSOs. EAPI was designed to be able to pass `__attribute__ ((visibility ("default")))` for symbols with GCC, which would mean that even if -fvisibility=hidden was used when compiling the library, the needed symbols would get exported. MSVC __almost__ works like GCC (or mingw) in which you can declare everything as export and it will just work (slower, but it will work). But there's a caveat: global variables will not work the same way for MSVC, but works for mingw and GCC. For global variables (as opposed to functions), MSVC requires correct DSO visibility for MSVC: instead of declaring a symbol as export for everything, you need to declare it as import when importing from another DSO and export when defining it locally. With current EAPI definitions, we get the following example working in mingw and MSVC (observe it doesn't define any global variables as exported symbols). Example 1: dll1: ``` EAPI void foo(void); EAPI void bar() { foo(); } ``` dll2: ``` EAPI void foo() { printf ("foo\n"); } ``` This works fine with API defined as __declspec(dllexport) in both cases and for gcc defining as `__atttribute__((visibility("default")))`. However, the following: Example 2: dll1: ``` EAPI extern int foo; EAPI void foobar(void); EAPI void bar() { foo = 5; foobar(); } ``` dll2: ``` EAPI int foo = 0; EAPI void foobar() { printf ("foo %d\n", foo); } ``` This will work on mingw but will not work for MSVC. And that's why LIBAPI is the only solution that works for MSVC. Co-authored-by: João Paulo Taylor Ienczak Zanette <jpaulotiz@gmail.com> Co-authored-by: Lucas Cavalcante de Sousa <lucks.sousa@gmail.com> Co-authored-by: Ricardo Campos <ricardo.campos@expertise.dev> Reviewers: jptiz, lucas, vtorri, woohyun Reviewed By: jptiz, lucas, vtorri Subscribers: cedric, #reviewers, #committers Tags: #efl Differential Revision: https://phab.enlightenment.org/D12203
2020-12-09 08:50:29 -08:00
EO_API EFL_VOID_FUNC_BODYV(efl_wref_add, EFL_FUNC_CALL(wref), Efl_Object **wref);
2017-04-26 06:01:44 -07:00
EOLIAN static void
_efl_object_wref_del(Eo *obj, Efl_Object_Data *pd, Eo **wref)
2013-12-25 06:13:41 -08:00
{
size_t count;
Efl_Object_Extension *ext = pd->ext;
2013-12-25 06:13:41 -08:00
// very unlikely so improve l1 instr cache by using goto
if (*wref != obj) goto err_wref_not_obj;
2013-12-25 06:13:41 -08:00
// very unlikely so improve l1 instr cache by using goto
if ((!ext) || (!ext->wrefs)) goto err_wref_none;
2013-12-25 06:13:41 -08:00
/* Move the last item in the array instead of the current wref. */
count = _wref_count(pd);
{
Eo ***itr;
for (itr = ext->wrefs; *itr; itr++)
2013-12-25 06:13:41 -08:00
{
if (*itr == wref)
{
*itr = ext->wrefs[count - 1];
2013-12-25 06:13:41 -08:00
break;
}
}
// very unlikely so improve l1 instr cache by using goto
if (!*itr) goto err_noiter;
2013-12-25 06:13:41 -08:00
}
if (count > 1)
{
Eo ***tmp;
// No count--; because of the NULL that is not included in the count
tmp = realloc(ext->wrefs, sizeof(*ext->wrefs) * count);
if (!tmp) return;
ext->wrefs = tmp;
ext->wrefs[count - 1] = NULL;
*wref = NULL;
return;
2013-12-25 06:13:41 -08:00
}
else
{
eina_freeq_ptr_main_add(ext->wrefs, free, 0);
ext->wrefs = NULL;
_efl_object_extension_noneed(pd);
2013-12-25 06:13:41 -08:00
}
*wref = NULL;
return;
err_noiter:
ERR("Wref %p is not associated with object %p", wref, obj);
goto err_null;
err_wref_none:
ERR("There are no weak refs for object %p", obj);
err_null:
*wref = NULL;
return;
err_wref_not_obj:
ERR("Wref is a weak ref to %p, while this function was called on %p.",
*wref, obj);
return;
2013-12-25 06:13:41 -08:00
}
eo: Rename EAPI macro to EO_API in Eo library Summary: Patch from a series of patches to rename EAPI symbols to specific library DSOs. = The Rationale = This patch is from a series of patches to rename EAPI symbols to specific library DSOs. EAPI was designed to be able to pass `__attribute__ ((visibility ("default")))` for symbols with GCC, which would mean that even if -fvisibility=hidden was used when compiling the library, the needed symbols would get exported. MSVC __almost__ works like GCC (or mingw) in which you can declare everything as export and it will just work (slower, but it will work). But there's a caveat: global variables will not work the same way for MSVC, but works for mingw and GCC. For global variables (as opposed to functions), MSVC requires correct DSO visibility for MSVC: instead of declaring a symbol as export for everything, you need to declare it as import when importing from another DSO and export when defining it locally. With current EAPI definitions, we get the following example working in mingw and MSVC (observe it doesn't define any global variables as exported symbols). Example 1: dll1: ``` EAPI void foo(void); EAPI void bar() { foo(); } ``` dll2: ``` EAPI void foo() { printf ("foo\n"); } ``` This works fine with API defined as __declspec(dllexport) in both cases and for gcc defining as `__atttribute__((visibility("default")))`. However, the following: Example 2: dll1: ``` EAPI extern int foo; EAPI void foobar(void); EAPI void bar() { foo = 5; foobar(); } ``` dll2: ``` EAPI int foo = 0; EAPI void foobar() { printf ("foo %d\n", foo); } ``` This will work on mingw but will not work for MSVC. And that's why LIBAPI is the only solution that works for MSVC. Co-authored-by: João Paulo Taylor Ienczak Zanette <jpaulotiz@gmail.com> Co-authored-by: Lucas Cavalcante de Sousa <lucks.sousa@gmail.com> Co-authored-by: Ricardo Campos <ricardo.campos@expertise.dev> Reviewers: jptiz, lucas, vtorri, woohyun Reviewed By: jptiz, lucas, vtorri Subscribers: cedric, #reviewers, #committers Tags: #efl Differential Revision: https://phab.enlightenment.org/D12203
2020-12-09 08:50:29 -08:00
EO_API EFL_VOID_FUNC_BODYV(efl_wref_del, EFL_FUNC_CALL(wref), Efl_Object **wref);
2017-04-26 06:01:44 -07:00
2013-12-25 06:13:41 -08:00
static inline void
_wref_destruct(Efl_Object_Data *pd)
2013-12-25 06:13:41 -08:00
{
Eo ***itr;
Efl_Object_Extension *ext = pd->ext;
2013-12-25 06:13:41 -08:00
if ((!ext) || (!ext->wrefs)) return;
for (itr = ext->wrefs; *itr; itr++) **itr = NULL;
eina_freeq_ptr_main_add(ext->wrefs, free, 0);
ext->wrefs = NULL;
2013-12-25 06:13:41 -08:00
}
/* EOF Weak reference. */
/* Event callbacks */
/* Callbacks */
/* XXX: Legacy support, remove when legacy is dead. */
static Eina_Hash *_legacy_events_hash = NULL;
eo: Rename EAPI macro to EO_API in Eo library Summary: Patch from a series of patches to rename EAPI symbols to specific library DSOs. = The Rationale = This patch is from a series of patches to rename EAPI symbols to specific library DSOs. EAPI was designed to be able to pass `__attribute__ ((visibility ("default")))` for symbols with GCC, which would mean that even if -fvisibility=hidden was used when compiling the library, the needed symbols would get exported. MSVC __almost__ works like GCC (or mingw) in which you can declare everything as export and it will just work (slower, but it will work). But there's a caveat: global variables will not work the same way for MSVC, but works for mingw and GCC. For global variables (as opposed to functions), MSVC requires correct DSO visibility for MSVC: instead of declaring a symbol as export for everything, you need to declare it as import when importing from another DSO and export when defining it locally. With current EAPI definitions, we get the following example working in mingw and MSVC (observe it doesn't define any global variables as exported symbols). Example 1: dll1: ``` EAPI void foo(void); EAPI void bar() { foo(); } ``` dll2: ``` EAPI void foo() { printf ("foo\n"); } ``` This works fine with API defined as __declspec(dllexport) in both cases and for gcc defining as `__atttribute__((visibility("default")))`. However, the following: Example 2: dll1: ``` EAPI extern int foo; EAPI void foobar(void); EAPI void bar() { foo = 5; foobar(); } ``` dll2: ``` EAPI int foo = 0; EAPI void foobar() { printf ("foo %d\n", foo); } ``` This will work on mingw but will not work for MSVC. And that's why LIBAPI is the only solution that works for MSVC. Co-authored-by: João Paulo Taylor Ienczak Zanette <jpaulotiz@gmail.com> Co-authored-by: Lucas Cavalcante de Sousa <lucks.sousa@gmail.com> Co-authored-by: Ricardo Campos <ricardo.campos@expertise.dev> Reviewers: jptiz, lucas, vtorri, woohyun Reviewed By: jptiz, lucas, vtorri Subscribers: cedric, #reviewers, #committers Tags: #efl Differential Revision: https://phab.enlightenment.org/D12203
2020-12-09 08:50:29 -08:00
EO_API const Efl_Event_Description *
efl_object_legacy_only_event_description_get(const char *_event_name)
{
Eina_Stringshare *event_name = eina_stringshare_add(_event_name);
Efl_Event_Description *event_desc = eina_hash_find(_legacy_events_hash, event_name);
if (!event_desc)
{
event_desc = calloc(1, sizeof(Efl_Event_Description));
event_desc->name = event_name;
event_desc->legacy_is = EINA_TRUE;
event_desc->unfreezable = EINA_TRUE;
eina_hash_add(_legacy_events_hash, event_name, event_desc);
}
else
{
eina_stringshare_del(event_name);
}
return event_desc;
}
static inline Eina_Bool
_legacy_event_desc_is(const Efl_Event_Description *desc)
{
return desc->legacy_is;
}
static void
_legacy_events_hash_free_cb(void *_desc)
{
Efl_Event_Description *desc = _desc;
eina_stringshare_del(desc->name);
eina_freeq_ptr_main_add(desc, free, sizeof(*desc));
}
/* EOF Legacy */
2013-12-25 06:13:41 -08:00
struct _Eo_Callback_Description
{
union
{
Efl_Callback_Array_Item item;
const Efl_Callback_Array_Item *item_array;
2013-12-25 06:13:41 -08:00
} items;
void *func_data;
Efl_Callback_Priority priority;
2013-12-25 06:13:41 -08:00
unsigned short generation;
2013-12-25 06:13:41 -08:00
Eina_Bool delete_me : 1;
Eina_Bool func_array : 1;
};
static Eina_Mempool *_eo_callback_mempool = NULL;
static Eina_Mempool *_efl_pending_future_mempool = NULL;
static Eina_Mempool *_efl_future_scheduler_entry_mempool = NULL;
static void
_eo_callback_free(Eo_Callback_Description *cb)
{
eina_mempool_free(_eo_callback_mempool, cb);
}
static Eo_Callback_Description *
_eo_callback_new(void)
{
return eina_mempool_calloc(_eo_callback_mempool,
sizeof(Eo_Callback_Description));
}
static void
_efl_pending_future_free(Efl_Future_Pending *pending)
{
eina_mempool_free(_efl_pending_future_mempool, pending);
}
static Efl_Future_Pending *
_efl_pending_future_new(void)
{
return eina_mempool_calloc(_efl_pending_future_mempool,
sizeof(Efl_Future_Pending));
}
#define CB_COUNT_INC(cnt) do { if ((cnt) != 0xffff) (cnt)++; } while(0)
#define CB_COUNT_DEC(cnt) do { if ((cnt) != 0xffff) (cnt)--; } while(0)
static inline unsigned char
_pointer_hash(const uintptr_t val)
{
static unsigned char shift = 0;
/* Sadly LLVM doesn't have log2 in its compile time optimization. So
we can not use static const here for portability sake. */
if (EINA_UNLIKELY((!shift)))
shift = (unsigned char) log2(1 + sizeof (Efl_Event_Description));
#ifdef EFL64
return (unsigned char)(((val) >> shift) & 0x3F);
#else
return (unsigned char)(((val) >> shift) & 0x1F);
#endif
}
#define EFL_OBJECT_EVENT_CB_INC(Obj, It, Pd, Event, Update_Hash) \
if (It->desc == Event && !Pd->event_cb_##Event) \
{ \
Update_Hash = EINA_FALSE; \
Pd->event_cb_##Event = EINA_TRUE; \
}
#define EFL_OBJECT_EVENT_CB_DEC(Obj, It, Pd, Event) \
if (It->desc == Event && Pd->event_cb_##Event) \
{ \
if (!efl_event_callback_count(Obj, Event)) \
Pd->event_cb_##Event = EINA_FALSE; \
}
static inline void
_special_event_count_inc(Eo *obj_id, Efl_Object_Data *pd, const Efl_Callback_Array_Item *it)
{
Eina_Bool update_hash = EINA_TRUE;
EFL_OBJECT_EVENT_CB_INC(obj_id, it, pd, EFL_EVENT_CALLBACK_ADD, update_hash)
else EFL_OBJECT_EVENT_CB_INC(obj_id, it, pd, EFL_EVENT_CALLBACK_DEL, update_hash)
else EFL_OBJECT_EVENT_CB_INC(obj_id, it, pd, EFL_EVENT_DEL, update_hash)
else EFL_OBJECT_EVENT_CB_INC(obj_id, it, pd, EFL_EVENT_INVALIDATE, update_hash)
else EFL_OBJECT_EVENT_CB_INC(obj_id, it, pd, EFL_EVENT_DESTRUCT, update_hash)
else if (it->desc == EFL_EVENT_NOREF && !pd->event_cb_EFL_EVENT_NOREF)
{
update_hash = EINA_FALSE;
EO_OBJ_POINTER_RETURN(obj_id, obj);
obj->noref_event = EINA_TRUE;
EO_OBJ_DONE(obj_id);
pd->event_cb_EFL_EVENT_NOREF = EINA_TRUE;
}
else if (it->desc == EFL_EVENT_OWNERSHIP_SHARED || it->desc == EFL_EVENT_OWNERSHIP_UNIQUE)
{
EO_OBJ_POINTER_RETURN(obj_id, obj);
obj->ownership_track = EINA_TRUE;
EO_OBJ_DONE(obj_id);
}
if (pd->ext && pd->ext->forwarders)
{
Efl_Event_Forwarder *forwarder;
Eina_List *l;
// Check if some event need to be forwarded now
EINA_LIST_FOREACH(eina_hash_find(pd->ext->forwarders, it->desc), l, forwarder)
{
if (!forwarder->source) continue;
if (forwarder->inserted) continue;
efl_event_callback_priority_add(forwarder->source,
forwarder->desc,
forwarder->priority,
_efl_event_forwarder_callback, obj_id);
forwarder->inserted = EINA_TRUE;
}
}
if (update_hash)
{
unsigned char event_hash;
event_hash = _pointer_hash((uintptr_t) it->desc);
pd->callbacks_mask |= 1ULL << event_hash;
}
}
static inline void
_special_event_count_dec(Eo *obj_id, Efl_Object_Data *pd, const Efl_Callback_Array_Item *it)
{
EFL_OBJECT_EVENT_CB_DEC(obj_id, it, pd, EFL_EVENT_CALLBACK_ADD)
else EFL_OBJECT_EVENT_CB_DEC(obj_id, it, pd, EFL_EVENT_CALLBACK_DEL)
else EFL_OBJECT_EVENT_CB_DEC(obj_id, it, pd, EFL_EVENT_DEL)
else EFL_OBJECT_EVENT_CB_DEC(obj_id, it, pd, EFL_EVENT_INVALIDATE)
else if (it->desc == EFL_EVENT_NOREF && pd->event_cb_EFL_EVENT_NOREF)
{
if (efl_event_callback_count(obj_id, EFL_EVENT_NOREF) == 0)
{
EO_OBJ_POINTER_RETURN(obj_id, obj);
obj->noref_event = EINA_FALSE;
EO_OBJ_DONE(obj_id);
pd->event_cb_EFL_EVENT_NOREF = EINA_FALSE;
}
}
}
2013-12-25 06:13:41 -08:00
/* Actually remove, doesn't care about walking list, or delete_me */
static void
_eo_callback_remove(Eo *obj, Efl_Object_Data *pd, Eo_Callback_Description **cb)
2013-12-25 06:13:41 -08:00
{
Eo_Callback_Description *tmp = *cb;
unsigned int length;
const Efl_Callback_Array_Item *it;
length = pd->callbacks_count - (cb - pd->callbacks);
if (length > 1)
memmove(cb, cb + 1, (length - 1) * sizeof(Eo_Callback_Description *));
pd->callbacks_count--;
if (_eo_nostep_alloc) pd->callbacks = realloc(pd->callbacks, pd->callbacks_count * sizeof (Eo_Callback_Description*));
if (pd->callbacks_count == 0)
{
free(pd->callbacks);
pd->callbacks = NULL;
}
if (tmp->func_array)
{
for (it = tmp->items.item_array; it->func; it++)
_special_event_count_dec(obj, pd, it);
}
else _special_event_count_dec(obj, pd, &(tmp->items.item));
_eo_callback_free(tmp);
2013-12-25 06:13:41 -08:00
}
/* Actually remove, doesn't care about walking list, or delete_me */
static void
_eo_callback_remove_all(Efl_Object_Data *pd)
2013-12-25 06:13:41 -08:00
{
unsigned int i;
for (i = 0; i < pd->callbacks_count; i++)
_eo_callback_free(pd->callbacks[i]);
eina_freeq_ptr_main_add(pd->callbacks, free, 0);
pd->callbacks = NULL;
pd->callbacks_count = 0;
pd->event_cb_EFL_EVENT_DESTRUCT = EINA_FALSE;
pd->event_cb_EFL_EVENT_CALLBACK_ADD = EINA_FALSE;
pd->event_cb_EFL_EVENT_CALLBACK_DEL = EINA_FALSE;
pd->event_cb_EFL_EVENT_DEL = EINA_FALSE;
pd->event_cb_EFL_EVENT_NOREF = EINA_FALSE;
pd->event_cb_EFL_EVENT_INVALIDATE = EINA_FALSE;
2013-12-25 06:13:41 -08:00
}
static void
_eo_callbacks_clear(Eo *obj, Efl_Object_Data *pd)
2013-12-25 06:13:41 -08:00
{
Eo_Callback_Description **itr;
unsigned int i = 0;
Eina_Bool remove_callbacks;
unsigned int generation_clamp;
2013-12-25 06:13:41 -08:00
/* If there are no deletions waiting. */
if (!pd->need_cleaning) return;
2013-12-25 06:13:41 -08:00
if (pd->event_frame)
{
/* there is still a event emission going on ... do not delete anything! */
remove_callbacks = EINA_FALSE;
/* if we are in event subscription we need to clamp the generations at the current frame otherwise we are possiblity not executing that later */
generation_clamp = pd->event_frame->generation;
}
else
{
/* no event emission running */
/* remove deleted callbacks */
remove_callbacks = EINA_TRUE;
/* clap to 0 generation */
generation_clamp = 0;
/* we dont need to clean later */
pd->need_cleaning = EINA_FALSE;
}
while (i < pd->callbacks_count)
2013-12-25 06:13:41 -08:00
{
itr = pd->callbacks + i;
if (remove_callbacks && (*itr)->delete_me)
{
_eo_callback_remove(obj, pd, itr);
}
else
{
if ((*itr)->generation > generation_clamp)
(*itr)->generation = generation_clamp;
i++;
}
2013-12-25 06:13:41 -08:00
}
}
static inline unsigned int
_eo_callback_search_sorted_near(const Efl_Object_Data *pd, const Eo_Callback_Description *look)
2013-12-25 06:13:41 -08:00
{
unsigned int start, last, middle;
const Eo_Callback_Description *p;
int cmp;
if (pd->callbacks_count == 0) return 0;
else if (pd->callbacks_count == 1) return 0;
2013-12-25 06:13:41 -08:00
start = 0;
last = pd->callbacks_count - 1;
do
2013-12-25 06:13:41 -08:00
{
middle = start + ((last - start) / 2);
p = pd->callbacks[middle];
cmp = p->priority - look->priority;
if (cmp == 0) return middle;
else if (cmp > 0) start = middle + 1;
else if (middle > 0) last = middle - 1;
else break;
2013-12-25 06:13:41 -08:00
}
while (start <= last);
return middle;
}
static void
_eo_callbacks_sorted_insert(Efl_Object_Data *pd, Eo_Callback_Description *cb)
{
Eo_Callback_Description **itr;
unsigned int length, j;
Efl_Event_Callback_Frame *frame;
// Do a dichotomic searh
j = _eo_callback_search_sorted_near(pd, cb);
// Adjust for both case of length == 0 and when priority is equal.
while ((j < pd->callbacks_count) &&
(pd->callbacks[j]->priority >= cb->priority)) j++;
// Increase the callbacks storage by 16 entries at a time
if (_eo_nostep_alloc || (pd->callbacks_count & 0xF) == 0x0)
2013-12-25 06:13:41 -08:00
{
Eo_Callback_Description **tmp;
2016-09-05 08:22:33 -07:00
unsigned int new_len = (pd->callbacks_count | 0xF) + 1;
if (_eo_nostep_alloc) new_len = pd->callbacks_count + 1;
tmp = realloc(pd->callbacks,
new_len * sizeof(Eo_Callback_Description *));
if (EINA_UNLIKELY(!tmp)) return;
pd->callbacks = tmp;
2013-12-25 06:13:41 -08:00
}
// FIXME: Potential improvement, merge single callback description of the same priority
// into an array when possible
itr = pd->callbacks + j;
length = pd->callbacks_count - j;
if (length > 0) memmove(itr + 1, itr,
length * sizeof(Eo_Callback_Description *));
*itr = cb;
pd->callbacks_count++;
// Update possible event emissions
for (frame = pd->event_frame; frame; frame = frame->next)
{
if ((itr - pd->callbacks) < (ptrdiff_t)frame->idx)
frame->inserted_before++;
}
2013-12-25 06:13:41 -08:00
}
static unsigned short
_efl_event_generation(Efl_Object_Data *pd)
{
if (!pd->event_frame) return 0;
return ((Efl_Event_Callback_Frame*)pd->event_frame)->generation;
}
EOLIAN static Eina_Bool
_efl_object_event_callback_priority_add(Eo *obj, Efl_Object_Data *pd,
const Efl_Event_Description *desc,
Efl_Callback_Priority priority,
Efl_Event_Cb func,
const void *user_data)
2013-12-25 06:13:41 -08:00
{
const Efl_Callback_Array_Item_Full arr[] =
{ {desc, priority, func, (void *)user_data}, {NULL, 0, NULL, NULL}};
Eo_Callback_Description *cb = _eo_callback_new();
#ifdef EO_DEBUG
unsigned int idx, r = 0, entries = 0;
for (idx = pd->callbacks_count ; idx > 0; idx--)
{
Eo_Callback_Description **cb;
cb = pd->callbacks + idx - 1;
if (!(*cb)->func_array)
{
if (((*cb)->items.item.desc == desc) &&
((*cb)->items.item.func == func) &&
((*cb)->priority == priority) &&
((*cb)->generation == _efl_event_generation(pd)))
r++;
}
entries++;
}
if (r > 1) INF("Object '%s' got %i callback with event '%s' registered.",
efl_debug_name_get(obj), r, desc->name);
if (entries > 10) INF("Object '%s' got %i callbacks.",
efl_debug_name_get(obj), entries);
#endif
2013-12-25 06:13:41 -08:00
// very unlikely so improve l1 instr cache by using goto
if (EINA_UNLIKELY(!cb || !desc || !func)) goto err;
2013-12-25 06:13:41 -08:00
cb->items.item.desc = desc;
cb->items.item.func = func;
cb->func_data = (void *)user_data;
2013-12-25 06:13:41 -08:00
cb->priority = priority;
cb->generation = _efl_event_generation(pd);
if (cb->generation) pd->need_cleaning = EINA_TRUE;
2013-12-25 06:13:41 -08:00
_eo_callbacks_sorted_insert(pd, cb);
_special_event_count_inc(obj, pd, &(cb->items.item));
2013-12-25 06:13:41 -08:00
if (pd->event_cb_EFL_EVENT_CALLBACK_ADD)
efl_event_callback_call(obj, EFL_EVENT_CALLBACK_ADD, (void *)arr);
return EINA_TRUE;
err: EINA_COLD
ERR("Tried adding callback with invalid values: cb: %p desc: %p func: %p", cb, desc, func);
_eo_callback_free(cb);
return EINA_FALSE;
2013-12-25 06:13:41 -08:00
}
eo: Rename EAPI macro to EO_API in Eo library Summary: Patch from a series of patches to rename EAPI symbols to specific library DSOs. = The Rationale = This patch is from a series of patches to rename EAPI symbols to specific library DSOs. EAPI was designed to be able to pass `__attribute__ ((visibility ("default")))` for symbols with GCC, which would mean that even if -fvisibility=hidden was used when compiling the library, the needed symbols would get exported. MSVC __almost__ works like GCC (or mingw) in which you can declare everything as export and it will just work (slower, but it will work). But there's a caveat: global variables will not work the same way for MSVC, but works for mingw and GCC. For global variables (as opposed to functions), MSVC requires correct DSO visibility for MSVC: instead of declaring a symbol as export for everything, you need to declare it as import when importing from another DSO and export when defining it locally. With current EAPI definitions, we get the following example working in mingw and MSVC (observe it doesn't define any global variables as exported symbols). Example 1: dll1: ``` EAPI void foo(void); EAPI void bar() { foo(); } ``` dll2: ``` EAPI void foo() { printf ("foo\n"); } ``` This works fine with API defined as __declspec(dllexport) in both cases and for gcc defining as `__atttribute__((visibility("default")))`. However, the following: Example 2: dll1: ``` EAPI extern int foo; EAPI void foobar(void); EAPI void bar() { foo = 5; foobar(); } ``` dll2: ``` EAPI int foo = 0; EAPI void foobar() { printf ("foo %d\n", foo); } ``` This will work on mingw but will not work for MSVC. And that's why LIBAPI is the only solution that works for MSVC. Co-authored-by: João Paulo Taylor Ienczak Zanette <jpaulotiz@gmail.com> Co-authored-by: Lucas Cavalcante de Sousa <lucks.sousa@gmail.com> Co-authored-by: Ricardo Campos <ricardo.campos@expertise.dev> Reviewers: jptiz, lucas, vtorri, woohyun Reviewed By: jptiz, lucas, vtorri Subscribers: cedric, #reviewers, #committers Tags: #efl Differential Revision: https://phab.enlightenment.org/D12203
2020-12-09 08:50:29 -08:00
EO_API EFL_FUNC_BODYV(efl_event_callback_priority_add,
Eina_Bool, 0, EFL_FUNC_CALL(desc, priority, cb, data),
const Efl_Event_Description *desc,
Efl_Callback_Priority priority,
Efl_Event_Cb cb, const void *data);
static void
_efl_object_event_callback_clean(Eo *obj, Efl_Object_Data *pd,
const Efl_Callback_Array_Item_Full *array,
Eo_Callback_Description **cb)
{
(*cb)->delete_me = EINA_TRUE;
if (pd->event_frame)
pd->need_cleaning = EINA_TRUE;
else
_eo_callback_remove(obj, pd, cb);
if (pd->event_cb_EFL_EVENT_CALLBACK_DEL)
efl_event_callback_call(obj, EFL_EVENT_CALLBACK_DEL, (void *)array);
}
EOLIAN static Eina_Bool
_efl_object_event_callback_del(Eo *obj, Efl_Object_Data *pd,
const Efl_Event_Description *desc,
Efl_Event_Cb func,
const void *user_data)
2013-12-25 06:13:41 -08:00
{
Eo_Callback_Description **cb;
unsigned int i;
2013-12-25 06:13:41 -08:00
for (cb = pd->callbacks, i = 0;
i < pd->callbacks_count;
cb++, i++)
2013-12-25 06:13:41 -08:00
{
if (!(*cb)->delete_me &&
((*cb)->items.item.desc == desc) &&
((*cb)->items.item.func == func) &&
((*cb)->func_data == user_data))
2013-12-25 06:13:41 -08:00
{
const Efl_Callback_Array_Item_Full arr[] =
{ {desc, (*cb)->priority, func, (*cb)->func_data}, {NULL, 0, NULL, NULL}};
2013-12-25 06:13:41 -08:00
_efl_object_event_callback_clean(obj, pd, arr, cb);
return EINA_TRUE;
2013-12-25 06:13:41 -08:00
}
}
DBG("Callback of object %p with function %p and data %p not found.", obj, func, user_data);
return EINA_FALSE;
2013-12-25 06:13:41 -08:00
}
eo: Rename EAPI macro to EO_API in Eo library Summary: Patch from a series of patches to rename EAPI symbols to specific library DSOs. = The Rationale = This patch is from a series of patches to rename EAPI symbols to specific library DSOs. EAPI was designed to be able to pass `__attribute__ ((visibility ("default")))` for symbols with GCC, which would mean that even if -fvisibility=hidden was used when compiling the library, the needed symbols would get exported. MSVC __almost__ works like GCC (or mingw) in which you can declare everything as export and it will just work (slower, but it will work). But there's a caveat: global variables will not work the same way for MSVC, but works for mingw and GCC. For global variables (as opposed to functions), MSVC requires correct DSO visibility for MSVC: instead of declaring a symbol as export for everything, you need to declare it as import when importing from another DSO and export when defining it locally. With current EAPI definitions, we get the following example working in mingw and MSVC (observe it doesn't define any global variables as exported symbols). Example 1: dll1: ``` EAPI void foo(void); EAPI void bar() { foo(); } ``` dll2: ``` EAPI void foo() { printf ("foo\n"); } ``` This works fine with API defined as __declspec(dllexport) in both cases and for gcc defining as `__atttribute__((visibility("default")))`. However, the following: Example 2: dll1: ``` EAPI extern int foo; EAPI void foobar(void); EAPI void bar() { foo = 5; foobar(); } ``` dll2: ``` EAPI int foo = 0; EAPI void foobar() { printf ("foo %d\n", foo); } ``` This will work on mingw but will not work for MSVC. And that's why LIBAPI is the only solution that works for MSVC. Co-authored-by: João Paulo Taylor Ienczak Zanette <jpaulotiz@gmail.com> Co-authored-by: Lucas Cavalcante de Sousa <lucks.sousa@gmail.com> Co-authored-by: Ricardo Campos <ricardo.campos@expertise.dev> Reviewers: jptiz, lucas, vtorri, woohyun Reviewed By: jptiz, lucas, vtorri Subscribers: cedric, #reviewers, #committers Tags: #efl Differential Revision: https://phab.enlightenment.org/D12203
2020-12-09 08:50:29 -08:00
EO_API EFL_FUNC_BODYV(efl_event_callback_del,
Eina_Bool, 0, EFL_FUNC_CALL(desc, func, user_data),
const Efl_Event_Description *desc,
Efl_Event_Cb func, const void *user_data);
EOLIAN static Eina_Bool
_efl_object_event_callback_array_priority_add(Eo *obj, Efl_Object_Data *pd,
const Efl_Callback_Array_Item *array,
Efl_Callback_Priority priority,
const void *user_data)
2013-12-25 06:13:41 -08:00
{
Eo_Callback_Description *cb = _eo_callback_new();
const Efl_Callback_Array_Item *it;
unsigned int num, i;
Efl_Callback_Array_Item_Full *ev_array;
#ifdef EO_DEBUG
const Efl_Callback_Array_Item *prev;
unsigned int idx, r = 0, entries = 0;
#endif
2013-12-25 06:13:41 -08:00
// very unlikely so improve l1 instr cache by using goto
if (!cb || !array) goto err;
#ifdef EO_DEBUG
prev = array;
for (it = prev + 1; prev->func && it->func; it++, prev++)
{
if (efl_callbacks_cmp(prev, it) > 0)
{
ERR("Trying to insert a non sorted array callbacks (%p).", array);
_eo_callback_free(cb);
return EINA_FALSE;
}
}
#endif
2013-12-25 06:13:41 -08:00
cb->func_data = (void *) user_data;
cb->priority = priority;
cb->items.item_array = array;
cb->func_array = EINA_TRUE;
cb->generation = _efl_event_generation(pd);
if (!!cb->generation) pd->need_cleaning = EINA_TRUE;
#ifdef EO_DEBUG
for (idx = pd->callbacks_count ; idx > 0; idx--)
{
Eo_Callback_Description **cb;
cb = pd->callbacks + idx - 1;
if ((*cb)->func_array)
{
if (((*cb)->items.item_array == array) &&
((*cb)->priority == priority) &&
((*cb)->generation == _efl_event_generation(pd)))
r++;
}
entries++;
}
if (r > 1)
{
Eina_Strbuf *buf = eina_strbuf_new();
Eina_Bool first = EINA_TRUE;
for (it = array; it->func; it++)
{
if (first) eina_strbuf_append(buf, it->desc->name);
else eina_strbuf_append_printf(buf, ", %s", it->desc->name);
first = EINA_FALSE;
}
INF("Object '%s' got %i callback with events array %s registered.",
efl_debug_name_get(obj), r, eina_strbuf_string_get(buf));
eina_strbuf_free(buf);
}
if (entries > 10) INF("Object '%s' got %i callbacks.",
efl_debug_name_get(obj), entries);
#endif
2013-12-25 06:13:41 -08:00
_eo_callbacks_sorted_insert(pd, cb);
for (it = cb->items.item_array; it->func; it++)
_special_event_count_inc(obj, pd, it);
2013-12-25 06:13:41 -08:00
num = 0;
for (it = cb->items.item_array; it->func; it++) num++;
ev_array = alloca((num + 1) * sizeof(Efl_Callback_Array_Item_Full));
for (i = 0, it = cb->items.item_array; it->func; it++, i++)
{
ev_array[i].desc = cb->items.item_array[i].desc;
ev_array[i].priority = cb->priority;
ev_array[i].func = cb->items.item_array[i].func;
ev_array[i].user_data = cb->func_data;
}
ev_array[i].desc = NULL;
ev_array[i].priority = 0;
ev_array[i].func = NULL;
ev_array[i].user_data = NULL;
if (pd->event_cb_EFL_EVENT_CALLBACK_ADD)
efl_event_callback_call(obj, EFL_EVENT_CALLBACK_ADD, ev_array);
return EINA_TRUE;
err:
ERR("Tried adding array of callbacks with invalid values: cb: %p array: %p.", cb, array);
_eo_callback_free(cb);
return EINA_FALSE;
2013-12-25 06:13:41 -08:00
}
eo: Rename EAPI macro to EO_API in Eo library Summary: Patch from a series of patches to rename EAPI symbols to specific library DSOs. = The Rationale = This patch is from a series of patches to rename EAPI symbols to specific library DSOs. EAPI was designed to be able to pass `__attribute__ ((visibility ("default")))` for symbols with GCC, which would mean that even if -fvisibility=hidden was used when compiling the library, the needed symbols would get exported. MSVC __almost__ works like GCC (or mingw) in which you can declare everything as export and it will just work (slower, but it will work). But there's a caveat: global variables will not work the same way for MSVC, but works for mingw and GCC. For global variables (as opposed to functions), MSVC requires correct DSO visibility for MSVC: instead of declaring a symbol as export for everything, you need to declare it as import when importing from another DSO and export when defining it locally. With current EAPI definitions, we get the following example working in mingw and MSVC (observe it doesn't define any global variables as exported symbols). Example 1: dll1: ``` EAPI void foo(void); EAPI void bar() { foo(); } ``` dll2: ``` EAPI void foo() { printf ("foo\n"); } ``` This works fine with API defined as __declspec(dllexport) in both cases and for gcc defining as `__atttribute__((visibility("default")))`. However, the following: Example 2: dll1: ``` EAPI extern int foo; EAPI void foobar(void); EAPI void bar() { foo = 5; foobar(); } ``` dll2: ``` EAPI int foo = 0; EAPI void foobar() { printf ("foo %d\n", foo); } ``` This will work on mingw but will not work for MSVC. And that's why LIBAPI is the only solution that works for MSVC. Co-authored-by: João Paulo Taylor Ienczak Zanette <jpaulotiz@gmail.com> Co-authored-by: Lucas Cavalcante de Sousa <lucks.sousa@gmail.com> Co-authored-by: Ricardo Campos <ricardo.campos@expertise.dev> Reviewers: jptiz, lucas, vtorri, woohyun Reviewed By: jptiz, lucas, vtorri Subscribers: cedric, #reviewers, #committers Tags: #efl Differential Revision: https://phab.enlightenment.org/D12203
2020-12-09 08:50:29 -08:00
EO_API EFL_FUNC_BODYV(efl_event_callback_array_priority_add,
Eina_Bool, 0, EFL_FUNC_CALL(array, priority, data),
const Efl_Callback_Array_Item *array,
Efl_Callback_Priority priority, const void *data);
EOLIAN static Eina_Bool
_efl_object_event_callback_array_del(Eo *obj, Efl_Object_Data *pd,
const Efl_Callback_Array_Item *array,
const void *user_data)
2013-12-25 06:13:41 -08:00
{
Eo_Callback_Description **cb;
unsigned int j;
2013-12-25 06:13:41 -08:00
for (cb = pd->callbacks, j = 0;
j < pd->callbacks_count;
cb++, j++)
2013-12-25 06:13:41 -08:00
{
if (!(*cb)->delete_me &&
((*cb)->items.item_array == array) &&
((*cb)->func_data == user_data))
2013-12-25 06:13:41 -08:00
{
const Efl_Callback_Array_Item *it;
unsigned int num, i;
Efl_Callback_Array_Item_Full *ev_array;
num = 0;
for (it = (*cb)->items.item_array; it->func; it++) num++;
ev_array = alloca((num + 1) * sizeof(Efl_Callback_Array_Item_Full));
for (i = 0, it = (*cb)->items.item_array; it->func; it++, i++)
{
ev_array[i].desc = (*cb)->items.item_array[i].desc;
ev_array[i].priority = (*cb)->priority;
ev_array[i].func = (*cb)->items.item_array[i].func;
ev_array[i].user_data = (*cb)->func_data;
}
ev_array[i].desc = NULL;
ev_array[i].priority = 0;
ev_array[i].func = NULL;
ev_array[i].user_data = NULL;
_efl_object_event_callback_clean(obj, pd, ev_array, cb);
return EINA_TRUE;
2013-12-25 06:13:41 -08:00
}
}
DBG("Callback of object %p with function array %p and data %p not found.", obj, array, user_data);
return EINA_FALSE;
2013-12-25 06:13:41 -08:00
}
eo: Rename EAPI macro to EO_API in Eo library Summary: Patch from a series of patches to rename EAPI symbols to specific library DSOs. = The Rationale = This patch is from a series of patches to rename EAPI symbols to specific library DSOs. EAPI was designed to be able to pass `__attribute__ ((visibility ("default")))` for symbols with GCC, which would mean that even if -fvisibility=hidden was used when compiling the library, the needed symbols would get exported. MSVC __almost__ works like GCC (or mingw) in which you can declare everything as export and it will just work (slower, but it will work). But there's a caveat: global variables will not work the same way for MSVC, but works for mingw and GCC. For global variables (as opposed to functions), MSVC requires correct DSO visibility for MSVC: instead of declaring a symbol as export for everything, you need to declare it as import when importing from another DSO and export when defining it locally. With current EAPI definitions, we get the following example working in mingw and MSVC (observe it doesn't define any global variables as exported symbols). Example 1: dll1: ``` EAPI void foo(void); EAPI void bar() { foo(); } ``` dll2: ``` EAPI void foo() { printf ("foo\n"); } ``` This works fine with API defined as __declspec(dllexport) in both cases and for gcc defining as `__atttribute__((visibility("default")))`. However, the following: Example 2: dll1: ``` EAPI extern int foo; EAPI void foobar(void); EAPI void bar() { foo = 5; foobar(); } ``` dll2: ``` EAPI int foo = 0; EAPI void foobar() { printf ("foo %d\n", foo); } ``` This will work on mingw but will not work for MSVC. And that's why LIBAPI is the only solution that works for MSVC. Co-authored-by: João Paulo Taylor Ienczak Zanette <jpaulotiz@gmail.com> Co-authored-by: Lucas Cavalcante de Sousa <lucks.sousa@gmail.com> Co-authored-by: Ricardo Campos <ricardo.campos@expertise.dev> Reviewers: jptiz, lucas, vtorri, woohyun Reviewed By: jptiz, lucas, vtorri Subscribers: cedric, #reviewers, #committers Tags: #efl Differential Revision: https://phab.enlightenment.org/D12203
2020-12-09 08:50:29 -08:00
EO_API EFL_FUNC_BODYV(efl_event_callback_array_del,
Eina_Bool, 0, EFL_FUNC_CALL(array, user_data),
const Efl_Callback_Array_Item *array,
const void *user_data);
typedef struct _Efl_Future_Scheduler Efl_Future_Scheduler;
typedef struct _Efl_Future_Scheduler_Entry Efl_Future_Scheduler_Entry;
struct _Efl_Future_Scheduler
{
Eina_Future_Scheduler scheduler;
const Efl_Callback_Array_Item *array;
const Eo *self;
Eina_List *futures;
Eina_Bool listener : 1;
};
struct _Efl_Future_Scheduler_Entry
{
Eina_Future_Schedule_Entry base;
Eina_Future_Scheduler_Cb cb;
Eina_Future *future;
Eina_Value value;
};
static Eina_Trash *schedulers_trash = NULL;
static unsigned char schedulers_count = 0;
static void
_future_scheduler_cleanup(Efl_Object_Data *pd)
{
if (eina_hash_population(pd->ext->schedulers)) return ;
eina_hash_free(pd->ext->schedulers);
pd->ext->schedulers = NULL;
_efl_object_extension_noneed(pd);
}
static void
_futures_dispatch_cb(void *data, const Efl_Event *ev EINA_UNUSED)
{
Efl_Future_Scheduler *sched = data;
Eina_List *entries = sched->futures;
Efl_Future_Scheduler_Entry *entry;
sched->futures = NULL;
efl_event_callback_array_del((Eo *) sched->self, sched->array, sched);
sched->listener = EINA_FALSE;
// Now trigger callbacks
EINA_LIST_FREE(entries, entry)
{
entry->cb(entry->future, entry->value);
eina_mempool_free(_efl_future_scheduler_entry_mempool, entry);
}
}
static void
_futures_cancel_cb(void *data)
{
Efl_Future_Scheduler *sched = data;
Eina_List *entries = sched->futures;
Efl_Future_Scheduler_Entry *entry;
efl_event_callback_array_del((Eo *) sched->self, sched->array, sched);
sched->listener = EINA_FALSE;
sched->futures = NULL;
EINA_LIST_FREE(entries, entry)
{
eina_future_cancel(entry->future);
eina_value_flush(&entry->value);
eina_mempool_free(_efl_future_scheduler_entry_mempool, entry);
}
if (schedulers_count > 8)
{
free(sched);
}
else
{
eina_trash_push(&schedulers_trash, sched);
schedulers_count++;
}
}
static Eina_Future_Schedule_Entry *
_efl_event_future_scheduler(Eina_Future_Scheduler *s_sched,
Eina_Future_Scheduler_Cb cb,
Eina_Future *future,
Eina_Value value)
{
Efl_Future_Scheduler *sched = (Efl_Future_Scheduler *)s_sched;
Efl_Future_Scheduler_Entry *entry;
entry = eina_mempool_malloc(_efl_future_scheduler_entry_mempool, sizeof(*entry));
EINA_SAFETY_ON_NULL_RETURN_VAL(entry, NULL);
entry->base.scheduler = &sched->scheduler;
entry->cb = cb;
entry->future = future;
entry->value = value;
if (!sched->listener)
{
efl_event_callback_array_add((Eo *) sched->self, sched->array, sched);
sched->listener = EINA_TRUE;
}
sched->futures = eina_list_append(sched->futures, entry);
return &entry->base;
}
static void
_efl_event_future_recall(Eina_Future_Schedule_Entry *s_entry)
{
Efl_Future_Scheduler_Entry *entry = (Efl_Future_Scheduler_Entry *)s_entry;
Efl_Future_Scheduler *sched;
Eina_List *lookup;
sched = (Efl_Future_Scheduler *) entry->base.scheduler;
lookup = eina_list_data_find_list(sched->futures, entry);
if (!lookup) return;
sched->futures = eina_list_remove_list(sched->futures, lookup);
if (!sched->futures)
{
Efl_Object_Data *pd = efl_data_scope_get(sched->self, EFL_OBJECT_CLASS);
_future_scheduler_cleanup(pd);
}
eina_value_flush(&entry->value);
eina_mempool_free(_efl_future_scheduler_entry_mempool, entry);
}
EOLIAN static Eina_Future_Scheduler *
_efl_object_event_future_scheduler_get(const Eo *obj, Efl_Object_Data *pd, Efl_Callback_Array_Item *array)
{
Efl_Object_Extension *ext;
Efl_Future_Scheduler *sched;
unsigned int i;
if (!array) return NULL;
ext = _efl_object_extension_need(pd);
EINA_SAFETY_ON_NULL_RETURN_VAL(ext, NULL);
// First lookup for an existing scheduler that match the provided array
if (!ext->schedulers) ext->schedulers = eina_hash_pointer_new(_futures_cancel_cb);
sched = eina_hash_find(ext->schedulers, &array);
if (sched) return &sched->scheduler;
// Define all the callback in the array to point to our internal callback,
// making the array ready to use.
for (i = 0; array[i].desc; i++)
array[i].func = _futures_dispatch_cb;
if (schedulers_count)
{
// Take one out of the trash for faster cycling
sched = eina_trash_pop(&schedulers_trash);
schedulers_count--;
}
else
{
// Need to allocate a new scheduler as none are on standby.
sched = calloc(1, sizeof (Efl_Future_Scheduler));
}
sched->scheduler.schedule = _efl_event_future_scheduler;
sched->scheduler.recall = _efl_event_future_recall;
sched->array = array;
sched->self = obj;
eina_hash_add(ext->schedulers, &array, sched);
return &sched->scheduler;
}
eo: Rename EAPI macro to EO_API in Eo library Summary: Patch from a series of patches to rename EAPI symbols to specific library DSOs. = The Rationale = This patch is from a series of patches to rename EAPI symbols to specific library DSOs. EAPI was designed to be able to pass `__attribute__ ((visibility ("default")))` for symbols with GCC, which would mean that even if -fvisibility=hidden was used when compiling the library, the needed symbols would get exported. MSVC __almost__ works like GCC (or mingw) in which you can declare everything as export and it will just work (slower, but it will work). But there's a caveat: global variables will not work the same way for MSVC, but works for mingw and GCC. For global variables (as opposed to functions), MSVC requires correct DSO visibility for MSVC: instead of declaring a symbol as export for everything, you need to declare it as import when importing from another DSO and export when defining it locally. With current EAPI definitions, we get the following example working in mingw and MSVC (observe it doesn't define any global variables as exported symbols). Example 1: dll1: ``` EAPI void foo(void); EAPI void bar() { foo(); } ``` dll2: ``` EAPI void foo() { printf ("foo\n"); } ``` This works fine with API defined as __declspec(dllexport) in both cases and for gcc defining as `__atttribute__((visibility("default")))`. However, the following: Example 2: dll1: ``` EAPI extern int foo; EAPI void foobar(void); EAPI void bar() { foo = 5; foobar(); } ``` dll2: ``` EAPI int foo = 0; EAPI void foobar() { printf ("foo %d\n", foo); } ``` This will work on mingw but will not work for MSVC. And that's why LIBAPI is the only solution that works for MSVC. Co-authored-by: João Paulo Taylor Ienczak Zanette <jpaulotiz@gmail.com> Co-authored-by: Lucas Cavalcante de Sousa <lucks.sousa@gmail.com> Co-authored-by: Ricardo Campos <ricardo.campos@expertise.dev> Reviewers: jptiz, lucas, vtorri, woohyun Reviewed By: jptiz, lucas, vtorri Subscribers: cedric, #reviewers, #committers Tags: #efl Differential Revision: https://phab.enlightenment.org/D12203
2020-12-09 08:50:29 -08:00
EO_API EFL_FUNC_BODYV_CONST(efl_event_future_scheduler_get,
Eina_Future_Scheduler *, 0, EFL_FUNC_CALL(array),
Efl_Callback_Array_Item *array);
eo: Rename EAPI macro to EO_API in Eo library Summary: Patch from a series of patches to rename EAPI symbols to specific library DSOs. = The Rationale = This patch is from a series of patches to rename EAPI symbols to specific library DSOs. EAPI was designed to be able to pass `__attribute__ ((visibility ("default")))` for symbols with GCC, which would mean that even if -fvisibility=hidden was used when compiling the library, the needed symbols would get exported. MSVC __almost__ works like GCC (or mingw) in which you can declare everything as export and it will just work (slower, but it will work). But there's a caveat: global variables will not work the same way for MSVC, but works for mingw and GCC. For global variables (as opposed to functions), MSVC requires correct DSO visibility for MSVC: instead of declaring a symbol as export for everything, you need to declare it as import when importing from another DSO and export when defining it locally. With current EAPI definitions, we get the following example working in mingw and MSVC (observe it doesn't define any global variables as exported symbols). Example 1: dll1: ``` EAPI void foo(void); EAPI void bar() { foo(); } ``` dll2: ``` EAPI void foo() { printf ("foo\n"); } ``` This works fine with API defined as __declspec(dllexport) in both cases and for gcc defining as `__atttribute__((visibility("default")))`. However, the following: Example 2: dll1: ``` EAPI extern int foo; EAPI void foobar(void); EAPI void bar() { foo = 5; foobar(); } ``` dll2: ``` EAPI int foo = 0; EAPI void foobar() { printf ("foo %d\n", foo); } ``` This will work on mingw but will not work for MSVC. And that's why LIBAPI is the only solution that works for MSVC. Co-authored-by: João Paulo Taylor Ienczak Zanette <jpaulotiz@gmail.com> Co-authored-by: Lucas Cavalcante de Sousa <lucks.sousa@gmail.com> Co-authored-by: Ricardo Campos <ricardo.campos@expertise.dev> Reviewers: jptiz, lucas, vtorri, woohyun Reviewed By: jptiz, lucas, vtorri Subscribers: cedric, #reviewers, #committers Tags: #efl Differential Revision: https://phab.enlightenment.org/D12203
2020-12-09 08:50:29 -08:00
EO_API unsigned int
_efl_object_event_callback_count(const Eo *obj EINA_UNUSED,
Efl_Object_Data *pd,
const Efl_Event_Description *desc)
{
unsigned int r = 0;
unsigned int idx;
for (idx = pd->callbacks_count ; idx > 0; idx--)
{
Eo_Callback_Description **cb;
cb = pd->callbacks + idx - 1;
if ((*cb)->func_array)
{
const Efl_Callback_Array_Item *it;
for (it = (*cb)->items.item_array; it->func; it++)
{
if (it->desc > desc) break;
if (it->desc == desc) r++;
}
}
else
{
if ((*cb)->items.item.desc == desc) r++;
}
}
return r;
}
eo: Rename EAPI macro to EO_API in Eo library Summary: Patch from a series of patches to rename EAPI symbols to specific library DSOs. = The Rationale = This patch is from a series of patches to rename EAPI symbols to specific library DSOs. EAPI was designed to be able to pass `__attribute__ ((visibility ("default")))` for symbols with GCC, which would mean that even if -fvisibility=hidden was used when compiling the library, the needed symbols would get exported. MSVC __almost__ works like GCC (or mingw) in which you can declare everything as export and it will just work (slower, but it will work). But there's a caveat: global variables will not work the same way for MSVC, but works for mingw and GCC. For global variables (as opposed to functions), MSVC requires correct DSO visibility for MSVC: instead of declaring a symbol as export for everything, you need to declare it as import when importing from another DSO and export when defining it locally. With current EAPI definitions, we get the following example working in mingw and MSVC (observe it doesn't define any global variables as exported symbols). Example 1: dll1: ``` EAPI void foo(void); EAPI void bar() { foo(); } ``` dll2: ``` EAPI void foo() { printf ("foo\n"); } ``` This works fine with API defined as __declspec(dllexport) in both cases and for gcc defining as `__atttribute__((visibility("default")))`. However, the following: Example 2: dll1: ``` EAPI extern int foo; EAPI void foobar(void); EAPI void bar() { foo = 5; foobar(); } ``` dll2: ``` EAPI int foo = 0; EAPI void foobar() { printf ("foo %d\n", foo); } ``` This will work on mingw but will not work for MSVC. And that's why LIBAPI is the only solution that works for MSVC. Co-authored-by: João Paulo Taylor Ienczak Zanette <jpaulotiz@gmail.com> Co-authored-by: Lucas Cavalcante de Sousa <lucks.sousa@gmail.com> Co-authored-by: Ricardo Campos <ricardo.campos@expertise.dev> Reviewers: jptiz, lucas, vtorri, woohyun Reviewed By: jptiz, lucas, vtorri Subscribers: cedric, #reviewers, #committers Tags: #efl Differential Revision: https://phab.enlightenment.org/D12203
2020-12-09 08:50:29 -08:00
EO_API EFL_FUNC_BODYV_CONST(efl_event_callback_count,
unsigned int, 0, EFL_FUNC_CALL(desc),
const Efl_Event_Description *desc);
static Eina_Bool
_cb_desc_match(const Efl_Event_Description *a, const Efl_Event_Description *b, Eina_Bool legacy_compare)
{
/* If one is legacy and the other is not, strcmp. Else, pointer compare. */
if (!EINA_UNLIKELY(legacy_compare && (_legacy_event_desc_is(a) != _legacy_event_desc_is(b))))
return (a == b);
return !strcmp(a->name, b->name);
}
#define EFL_OBJECT_EVENT_CALLBACK_BLOCK(Pd, Desc, Event, Need_Hash) \
if (Desc == Event) \
{ \
if (!(Pd->event_cb_##Event)) return EINA_TRUE; \
Need_Hash = EINA_FALSE; \
} \
static inline Eina_Bool
_event_callback_call(Eo *obj_id, Efl_Object_Data *pd,
const Efl_Event_Description *desc,
void *event_info,
Eina_Bool legacy_compare)
2013-12-25 06:13:41 -08:00
{
Eo_Callback_Description **cb;
eo: event callback call optimization a little overfiew to how eos event emission is working: - In eo there are 2 types of events restart events and normal events. Normals are *always* emitted from callback_max to 0 Restarts are emitted from the previous emissions current idx to 0. The previous emission will stop then - To keep track of the previous event emissions for restarts there was an eina inlist. - To keep track of other things in eo, there was an additional eo event stack frame (newly inserted events etc. etc.) This commit now uses this event stack frame for implementing the details about the restart events. This has the advatage that every efl_object_data contains one byte less, and the up to date keeping of the id's in the restart infrastructure is not needed anymore, making the whole event emission code less instructions and faster. How this now works: - Every emission has a event emission frame, when the emission starts, the frame is added, next points to the next older event emission. In this event stack frame we are storing the current idx, the description and a few other things that are not really relevant at this point. - when a restart event is started, this event stack is searched from the current frame up to the next one featuring the same event description. The event frame stack is then remembered, if the event emission is done, the current idx (normally 0 or something higher when callback was stopped) is then copyied back to the earlier frame. - Based on the nature of the event frame stacks, the idx is updated every iteration. And for the restart events, we only need to know the next, which removes the need of permanently updating the idx in the current stack. - The event frame stack is not allocated on the heap, hence more things in there does not matter at all. Reviewed-by: Cedric BAIL <cedric.bail@free.fr> Differential Revision: https://phab.enlightenment.org/D12097
2020-08-05 01:45:29 -07:00
Efl_Event_Callback_Frame *restart_lookup = NULL; //a pointer to a frame, which is high up the stack, which we use to restore
Efl_Event ev;
unsigned int idx;
Eina_Bool callback_already_stopped, ret;
Efl_Event_Callback_Frame frame = {
eo: event callback call optimization a little overfiew to how eos event emission is working: - In eo there are 2 types of events restart events and normal events. Normals are *always* emitted from callback_max to 0 Restarts are emitted from the previous emissions current idx to 0. The previous emission will stop then - To keep track of the previous event emissions for restarts there was an eina inlist. - To keep track of other things in eo, there was an additional eo event stack frame (newly inserted events etc. etc.) This commit now uses this event stack frame for implementing the details about the restart events. This has the advatage that every efl_object_data contains one byte less, and the up to date keeping of the id's in the restart infrastructure is not needed anymore, making the whole event emission code less instructions and faster. How this now works: - Every emission has a event emission frame, when the emission starts, the frame is added, next points to the next older event emission. In this event stack frame we are storing the current idx, the description and a few other things that are not really relevant at this point. - when a restart event is started, this event stack is searched from the current frame up to the next one featuring the same event description. The event frame stack is then remembered, if the event emission is done, the current idx (normally 0 or something higher when callback was stopped) is then copyied back to the earlier frame. - Based on the nature of the event frame stacks, the idx is updated every iteration. And for the restart events, we only need to know the next, which removes the need of permanently updating the idx in the current stack. - The event frame stack is not allocated on the heap, hence more things in there does not matter at all. Reviewed-by: Cedric BAIL <cedric.bail@free.fr> Differential Revision: https://phab.enlightenment.org/D12097
2020-08-05 01:45:29 -07:00
.desc = desc,
.next = NULL,
.idx = 0,
.inserted_before = 0,
.generation = 1,
};
Eina_Bool need_hash = EINA_TRUE;
if (pd->callbacks_count == 0) return EINA_TRUE;
else EFL_OBJECT_EVENT_CALLBACK_BLOCK(pd, desc, EFL_EVENT_CALLBACK_ADD, need_hash)
else EFL_OBJECT_EVENT_CALLBACK_BLOCK(pd, desc, EFL_EVENT_CALLBACK_DEL, need_hash)
else EFL_OBJECT_EVENT_CALLBACK_BLOCK(pd, desc, EFL_EVENT_DEL, need_hash)
else EFL_OBJECT_EVENT_CALLBACK_BLOCK(pd, desc, EFL_EVENT_INVALIDATE, need_hash)
else EFL_OBJECT_EVENT_CALLBACK_BLOCK(pd, desc, EFL_EVENT_NOREF, need_hash)
else EFL_OBJECT_EVENT_CALLBACK_BLOCK(pd, desc, EFL_EVENT_DESTRUCT, need_hash)
if (EINA_LIKELY(!legacy_compare && need_hash))
{
unsigned char event_hash;
event_hash = _pointer_hash((uintptr_t) desc);
if (!(pd->callbacks_mask & (1ULL << event_hash)))
return EINA_TRUE;
}
if (pd->event_frame)
frame.generation = ((Efl_Event_Callback_Frame*)pd->event_frame)->generation + 1;
EVENT_STACK_PUSH(pd, &frame);
callback_already_stopped = pd->callback_stopped;
pd->callback_stopped = EINA_FALSE;
ret = EINA_TRUE;
ev.object = obj_id;
ev.desc = desc;
ev.info = event_info;
2013-12-25 06:13:41 -08:00
// Handle event that require to restart where we were in the nested list walking
// relatively unlikely so improve l1 instr cache by using goto
if (desc->restart) goto restart;
else idx = pd->callbacks_count;
restart_back:
for (; idx > 0; idx--)
2013-12-25 06:13:41 -08:00
{
frame.idx = idx;
cb = pd->callbacks + idx - 1;
if (!(*cb)->delete_me)
2013-12-25 06:13:41 -08:00
{
if ((*cb)->generation >= frame.generation)
continue;
if ((*cb)->func_array)
{
const Efl_Callback_Array_Item *it;
2013-12-25 06:13:41 -08:00
for (it = (*cb)->items.item_array; it->func; it++)
{
// Array callbacks are sorted, break if we are getting to high.
if (!legacy_compare &&
((const unsigned char *) desc < (const unsigned char *) it->desc))
break;
if (!_cb_desc_match(it->desc, desc, legacy_compare))
continue;
if (!it->desc->unfreezable &&
(event_freeze_count || pd->event_freeze_count))
continue;
it->func((void *) (*cb)->func_data, &ev);
/* Abort callback calling if the func says so. */
if (pd->callback_stopped)
{
ret = EINA_FALSE;
goto end;
}
}
}
else
2013-12-25 06:13:41 -08:00
{
if (!_cb_desc_match((*cb)->items.item.desc, desc, legacy_compare))
continue;
if (!(*cb)->items.item.desc->unfreezable &&
(event_freeze_count || pd->event_freeze_count))
2013-12-25 06:13:41 -08:00
continue;
(*cb)->items.item.func((void *) (*cb)->func_data, &ev);
2013-12-25 06:13:41 -08:00
/* Abort callback calling if the func says so. */
if (pd->callback_stopped)
2013-12-25 06:13:41 -08:00
{
ret = EINA_FALSE;
goto end;
}
}
}
eo: event callback call optimization a little overfiew to how eos event emission is working: - In eo there are 2 types of events restart events and normal events. Normals are *always* emitted from callback_max to 0 Restarts are emitted from the previous emissions current idx to 0. The previous emission will stop then - To keep track of the previous event emissions for restarts there was an eina inlist. - To keep track of other things in eo, there was an additional eo event stack frame (newly inserted events etc. etc.) This commit now uses this event stack frame for implementing the details about the restart events. This has the advatage that every efl_object_data contains one byte less, and the up to date keeping of the id's in the restart infrastructure is not needed anymore, making the whole event emission code less instructions and faster. How this now works: - Every emission has a event emission frame, when the emission starts, the frame is added, next points to the next older event emission. In this event stack frame we are storing the current idx, the description and a few other things that are not really relevant at this point. - when a restart event is started, this event stack is searched from the current frame up to the next one featuring the same event description. The event frame stack is then remembered, if the event emission is done, the current idx (normally 0 or something higher when callback was stopped) is then copyied back to the earlier frame. - Based on the nature of the event frame stacks, the idx is updated every iteration. And for the restart events, we only need to know the next, which removes the need of permanently updating the idx in the current stack. - The event frame stack is not allocated on the heap, hence more things in there does not matter at all. Reviewed-by: Cedric BAIL <cedric.bail@free.fr> Differential Revision: https://phab.enlightenment.org/D12097
2020-08-05 01:45:29 -07:00
/*
* copy back the idx that might have changed due to restarts, (theoretically only needed with restarts, condition made everything slower)
* additionally adjust to event subscriptions that have been added in a event callback
*/
idx = frame.idx + frame.inserted_before;
frame.inserted_before = 0;
2013-12-25 06:13:41 -08:00
}
end:
// Handling restarting list walking complete exit.
// This must be 1, we copy back the frame idx at the end of the for loop.
// The next iteration then decrements the idx by 1 which results in the effective running idx of that frame beeing 0
if (restart_lookup) restart_lookup->idx = 1;
EVENT_STACK_POP(pd);
_eo_callbacks_clear(obj_id, pd);
2013-12-25 06:13:41 -08:00
pd->callback_stopped = callback_already_stopped;
2013-12-25 06:13:41 -08:00
return ret;
restart:
eo: event callback call optimization a little overfiew to how eos event emission is working: - In eo there are 2 types of events restart events and normal events. Normals are *always* emitted from callback_max to 0 Restarts are emitted from the previous emissions current idx to 0. The previous emission will stop then - To keep track of the previous event emissions for restarts there was an eina inlist. - To keep track of other things in eo, there was an additional eo event stack frame (newly inserted events etc. etc.) This commit now uses this event stack frame for implementing the details about the restart events. This has the advatage that every efl_object_data contains one byte less, and the up to date keeping of the id's in the restart infrastructure is not needed anymore, making the whole event emission code less instructions and faster. How this now works: - Every emission has a event emission frame, when the emission starts, the frame is added, next points to the next older event emission. In this event stack frame we are storing the current idx, the description and a few other things that are not really relevant at this point. - when a restart event is started, this event stack is searched from the current frame up to the next one featuring the same event description. The event frame stack is then remembered, if the event emission is done, the current idx (normally 0 or something higher when callback was stopped) is then copyied back to the earlier frame. - Based on the nature of the event frame stacks, the idx is updated every iteration. And for the restart events, we only need to know the next, which removes the need of permanently updating the idx in the current stack. - The event frame stack is not allocated on the heap, hence more things in there does not matter at all. Reviewed-by: Cedric BAIL <cedric.bail@free.fr> Differential Revision: https://phab.enlightenment.org/D12097
2020-08-05 01:45:29 -07:00
// Search for the next frame that has the same event description
for (restart_lookup = frame.next; restart_lookup; restart_lookup = restart_lookup->next)
{
eo: event callback call optimization a little overfiew to how eos event emission is working: - In eo there are 2 types of events restart events and normal events. Normals are *always* emitted from callback_max to 0 Restarts are emitted from the previous emissions current idx to 0. The previous emission will stop then - To keep track of the previous event emissions for restarts there was an eina inlist. - To keep track of other things in eo, there was an additional eo event stack frame (newly inserted events etc. etc.) This commit now uses this event stack frame for implementing the details about the restart events. This has the advatage that every efl_object_data contains one byte less, and the up to date keeping of the id's in the restart infrastructure is not needed anymore, making the whole event emission code less instructions and faster. How this now works: - Every emission has a event emission frame, when the emission starts, the frame is added, next points to the next older event emission. In this event stack frame we are storing the current idx, the description and a few other things that are not really relevant at this point. - when a restart event is started, this event stack is searched from the current frame up to the next one featuring the same event description. The event frame stack is then remembered, if the event emission is done, the current idx (normally 0 or something higher when callback was stopped) is then copyied back to the earlier frame. - Based on the nature of the event frame stacks, the idx is updated every iteration. And for the restart events, we only need to know the next, which removes the need of permanently updating the idx in the current stack. - The event frame stack is not allocated on the heap, hence more things in there does not matter at all. Reviewed-by: Cedric BAIL <cedric.bail@free.fr> Differential Revision: https://phab.enlightenment.org/D12097
2020-08-05 01:45:29 -07:00
if (restart_lookup->desc == desc) break;
}
eo: event callback call optimization a little overfiew to how eos event emission is working: - In eo there are 2 types of events restart events and normal events. Normals are *always* emitted from callback_max to 0 Restarts are emitted from the previous emissions current idx to 0. The previous emission will stop then - To keep track of the previous event emissions for restarts there was an eina inlist. - To keep track of other things in eo, there was an additional eo event stack frame (newly inserted events etc. etc.) This commit now uses this event stack frame for implementing the details about the restart events. This has the advatage that every efl_object_data contains one byte less, and the up to date keeping of the id's in the restart infrastructure is not needed anymore, making the whole event emission code less instructions and faster. How this now works: - Every emission has a event emission frame, when the emission starts, the frame is added, next points to the next older event emission. In this event stack frame we are storing the current idx, the description and a few other things that are not really relevant at this point. - when a restart event is started, this event stack is searched from the current frame up to the next one featuring the same event description. The event frame stack is then remembered, if the event emission is done, the current idx (normally 0 or something higher when callback was stopped) is then copyied back to the earlier frame. - Based on the nature of the event frame stacks, the idx is updated every iteration. And for the restart events, we only need to know the next, which removes the need of permanently updating the idx in the current stack. - The event frame stack is not allocated on the heap, hence more things in there does not matter at all. Reviewed-by: Cedric BAIL <cedric.bail@free.fr> Differential Revision: https://phab.enlightenment.org/D12097
2020-08-05 01:45:29 -07:00
// Ensure that the idx is the next from the previous run, minimum number 0
if (restart_lookup) {
idx = restart_lookup->idx - 1;
} else {
idx = 0;
}
// If this is 0, then we are restarting
if (!idx)
idx = pd->callbacks_count;
goto restart_back;
2013-12-25 06:13:41 -08:00
}
EOLIAN static Eina_Bool
_efl_object_event_callback_call(Eo *obj_id, Efl_Object_Data *pd,
const Efl_Event_Description *desc,
void *event_info)
{
return _event_callback_call(obj_id, pd, desc, event_info, EINA_FALSE);
}
eo: Rename EAPI macro to EO_API in Eo library Summary: Patch from a series of patches to rename EAPI symbols to specific library DSOs. = The Rationale = This patch is from a series of patches to rename EAPI symbols to specific library DSOs. EAPI was designed to be able to pass `__attribute__ ((visibility ("default")))` for symbols with GCC, which would mean that even if -fvisibility=hidden was used when compiling the library, the needed symbols would get exported. MSVC __almost__ works like GCC (or mingw) in which you can declare everything as export and it will just work (slower, but it will work). But there's a caveat: global variables will not work the same way for MSVC, but works for mingw and GCC. For global variables (as opposed to functions), MSVC requires correct DSO visibility for MSVC: instead of declaring a symbol as export for everything, you need to declare it as import when importing from another DSO and export when defining it locally. With current EAPI definitions, we get the following example working in mingw and MSVC (observe it doesn't define any global variables as exported symbols). Example 1: dll1: ``` EAPI void foo(void); EAPI void bar() { foo(); } ``` dll2: ``` EAPI void foo() { printf ("foo\n"); } ``` This works fine with API defined as __declspec(dllexport) in both cases and for gcc defining as `__atttribute__((visibility("default")))`. However, the following: Example 2: dll1: ``` EAPI extern int foo; EAPI void foobar(void); EAPI void bar() { foo = 5; foobar(); } ``` dll2: ``` EAPI int foo = 0; EAPI void foobar() { printf ("foo %d\n", foo); } ``` This will work on mingw but will not work for MSVC. And that's why LIBAPI is the only solution that works for MSVC. Co-authored-by: João Paulo Taylor Ienczak Zanette <jpaulotiz@gmail.com> Co-authored-by: Lucas Cavalcante de Sousa <lucks.sousa@gmail.com> Co-authored-by: Ricardo Campos <ricardo.campos@expertise.dev> Reviewers: jptiz, lucas, vtorri, woohyun Reviewed By: jptiz, lucas, vtorri Subscribers: cedric, #reviewers, #committers Tags: #efl Differential Revision: https://phab.enlightenment.org/D12203
2020-12-09 08:50:29 -08:00
EO_API EFL_FUNC_BODYV(efl_event_callback_call,
Eina_Bool, 0, EFL_FUNC_CALL(desc, event_info),
const Efl_Event_Description *desc, void *event_info);
EOLIAN static Eina_Bool
_efl_object_event_callback_legacy_call(Eo *obj_id, Efl_Object_Data *pd,
const Efl_Event_Description *desc,
void *event_info)
{
return _event_callback_call(obj_id, pd, desc, event_info, EINA_TRUE);
}
eo: Rename EAPI macro to EO_API in Eo library Summary: Patch from a series of patches to rename EAPI symbols to specific library DSOs. = The Rationale = This patch is from a series of patches to rename EAPI symbols to specific library DSOs. EAPI was designed to be able to pass `__attribute__ ((visibility ("default")))` for symbols with GCC, which would mean that even if -fvisibility=hidden was used when compiling the library, the needed symbols would get exported. MSVC __almost__ works like GCC (or mingw) in which you can declare everything as export and it will just work (slower, but it will work). But there's a caveat: global variables will not work the same way for MSVC, but works for mingw and GCC. For global variables (as opposed to functions), MSVC requires correct DSO visibility for MSVC: instead of declaring a symbol as export for everything, you need to declare it as import when importing from another DSO and export when defining it locally. With current EAPI definitions, we get the following example working in mingw and MSVC (observe it doesn't define any global variables as exported symbols). Example 1: dll1: ``` EAPI void foo(void); EAPI void bar() { foo(); } ``` dll2: ``` EAPI void foo() { printf ("foo\n"); } ``` This works fine with API defined as __declspec(dllexport) in both cases and for gcc defining as `__atttribute__((visibility("default")))`. However, the following: Example 2: dll1: ``` EAPI extern int foo; EAPI void foobar(void); EAPI void bar() { foo = 5; foobar(); } ``` dll2: ``` EAPI int foo = 0; EAPI void foobar() { printf ("foo %d\n", foo); } ``` This will work on mingw but will not work for MSVC. And that's why LIBAPI is the only solution that works for MSVC. Co-authored-by: João Paulo Taylor Ienczak Zanette <jpaulotiz@gmail.com> Co-authored-by: Lucas Cavalcante de Sousa <lucks.sousa@gmail.com> Co-authored-by: Ricardo Campos <ricardo.campos@expertise.dev> Reviewers: jptiz, lucas, vtorri, woohyun Reviewed By: jptiz, lucas, vtorri Subscribers: cedric, #reviewers, #committers Tags: #efl Differential Revision: https://phab.enlightenment.org/D12203
2020-12-09 08:50:29 -08:00
EO_API EFL_FUNC_BODYV(efl_event_callback_legacy_call,
Eina_Bool, 0, EFL_FUNC_CALL(desc, event_info),
const Efl_Event_Description *desc, void *event_info);
EOLIAN static void
_efl_object_event_callback_stop(Eo *obj EINA_UNUSED, Efl_Object_Data *pd)
{
pd->callback_stopped = EINA_TRUE;
}
static void
_efl_event_forwarder_callback(void *data, const Efl_Event *event)
2013-12-25 06:13:41 -08:00
{
Eo *new_obj = (Eo *) data;
Eina_Bool ret = EINA_FALSE;
2013-12-25 06:13:41 -08:00
ret = efl_event_callback_call(new_obj, event->desc, event->info);
if (!ret)
{
efl_event_callback_stop(event->object);
}
2013-12-25 06:13:41 -08:00
}
static void
_forwarders_list_clean(void *data)
{
Efl_Event_Forwarder *forwarder;
Eina_List *l = data;
EINA_LIST_FREE(l, forwarder)
{
if (forwarder->source)
{
if (forwarder->inserted)
efl_event_callback_del(forwarder->source,
forwarder->desc,
_efl_event_forwarder_callback,
forwarder->new_obj);
efl_wref_del(forwarder->source, &forwarder->source);
}
free(forwarder);
}
}
EOLIAN static void
_efl_object_event_callback_forwarder_priority_add(Eo *obj, Efl_Object_Data *pd EINA_UNUSED,
const Efl_Event_Description *desc,
short priority,
Eo *new_obj)
2013-12-25 06:13:41 -08:00
{
EO_OBJ_POINTER_RETURN(new_obj, new_data);
EO_OBJ_DONE(new_obj);
Efl_Event_Forwarder *forwarder;
Efl_Object_Extension *ext;
Efl_Object_Data *dpd;
Eina_List *l;
dpd = efl_data_scope_safe_get(new_obj, EFL_OBJECT_CLASS);
EINA_SAFETY_ON_NULL_RETURN(dpd);
ext = _efl_object_extension_need(dpd);
EINA_SAFETY_ON_NULL_RETURN(ext);
// Prevent double insertion for the same object source and event description
EINA_LIST_FOREACH(eina_hash_find(ext->forwarders, desc), l, forwarder)
{
if (forwarder->desc == desc &&
forwarder->new_obj == new_obj &&
forwarder->source == obj)
{
ERR("Forwarder added on '%s' for event '%s' toward '%s' has already been set.\n",
efl_debug_name_get(obj), desc->name, efl_debug_name_get(new_obj));
return;
}
}
forwarder = malloc(sizeof (Efl_Event_Forwarder));
EINA_SAFETY_ON_NULL_RETURN(forwarder);
forwarder->desc = desc;
forwarder->priority = priority;
forwarder->new_obj = new_obj;
efl_wref_add(obj, &forwarder->source);
if (efl_event_callback_count(new_obj, desc) > 0)
{
efl_event_callback_priority_add(obj, desc, priority, _efl_event_forwarder_callback, new_obj);
forwarder->inserted = EINA_TRUE;
}
else
{
forwarder->inserted = EINA_FALSE;
}
2013-12-25 06:13:41 -08:00
if (!ext->forwarders)
ext->forwarders = eina_hash_pointer_new(_forwarders_list_clean);
eina_hash_list_direct_append(ext->forwarders, forwarder->desc, forwarder);
2013-12-25 06:13:41 -08:00
}
EOLIAN static void
_efl_object_event_callback_forwarder_del(Eo *obj, Efl_Object_Data *pd EINA_UNUSED,
const Efl_Event_Description *desc,
Eo *new_obj)
2013-12-25 06:13:41 -08:00
{
EO_OBJ_POINTER_RETURN(new_obj, new_data);
EO_OBJ_DONE(new_obj);
Efl_Event_Forwarder *forwarder;
Efl_Object_Extension *ext;
Efl_Object_Data *dpd;
Eina_List *l, *tofree = NULL;
2013-12-25 06:13:41 -08:00
dpd = efl_data_scope_safe_get(new_obj, EFL_OBJECT_CLASS);
if (!dpd) return ;
ext = dpd->ext;
if (!ext) return ;
EINA_LIST_FOREACH(eina_hash_find(ext->forwarders, desc), l, forwarder)
{
// Remove dead source at the same time we remove any forwader
if (forwarder->source == obj || forwarder->source == NULL)
tofree = eina_list_append(tofree, forwarder);
}
EINA_LIST_FREE(tofree, forwarder)
{
if (forwarder->source)
{
if (forwarder->inserted)
efl_event_callback_del(obj, desc, _efl_event_forwarder_callback, new_obj);
efl_wref_del(obj, &forwarder->source);
}
eina_hash_list_remove(ext->forwarders, desc, forwarder);
free(forwarder);
}
2013-12-25 06:13:41 -08:00
}
EOLIAN static void
_efl_object_event_freeze(Eo *obj EINA_UNUSED, Efl_Object_Data *pd)
2013-12-25 06:13:41 -08:00
{
pd->event_freeze_count++;
}
EOLIAN static void
_efl_object_event_thaw(Eo *obj, Efl_Object_Data *pd)
2013-12-25 06:13:41 -08:00
{
if (pd->event_freeze_count > 0)
{
pd->event_freeze_count--;
}
else
{
ERR("Events for object %p have already been thawed.", obj);
}
}
EOLIAN static int
_efl_object_event_freeze_count_get(const Eo *obj EINA_UNUSED, Efl_Object_Data *pd)
2013-12-25 06:13:41 -08:00
{
return pd->event_freeze_count;
}
EOLIAN static void
_efl_object_event_global_freeze(void)
2013-12-25 06:13:41 -08:00
{
event_freeze_count++;
}
EOLIAN static void
_efl_object_event_global_thaw(void)
2013-12-25 06:13:41 -08:00
{
if (event_freeze_count > 0)
{
event_freeze_count--;
}
else
{
ERR("Global events have already been thawed.");
}
}
EOLIAN static int
_efl_object_event_global_freeze_count_get(void)
2013-12-25 06:13:41 -08:00
{
return event_freeze_count;
}
EOLIAN static Eina_Bool
_efl_object_composite_attach(Eo *parent_id, Efl_Object_Data *pd EINA_UNUSED, Eo *comp_obj_id)
{
Efl_Object_Optional *opt;
Eo *emb_obj_id = NULL;
EO_OBJ_POINTER_RETURN_VAL(comp_obj_id, comp_obj, EINA_FALSE);
EO_OBJ_POINTER_GOTO(parent_id, parent, err_parent);
/* FIXME: composite should fail if domains are different */
/* Don't composite if we already have a composite object of this type */
{
Eina_List *itr;
EINA_LIST_FOREACH(parent->opt->composite_objects, itr, emb_obj_id)
{
EO_OBJ_POINTER_GOTO(emb_obj_id, emb_obj, err_klass);
if (EINA_UNLIKELY(emb_obj->klass == comp_obj->klass)) goto err_klass;
}
emb_obj_id = NULL;
}
Efl_Object_Data *comp_pd = efl_data_scope_get(comp_obj_id, EFL_OBJECT_CLASS);
if (efl_composite_part_is(comp_obj_id))
efl_composite_detach(comp_pd->ext->composite_parent, comp_obj_id);
/* Set the parent comp on the child. */
_efl_object_extension_need(comp_pd);
comp_pd->ext->composite_parent = parent_id;
opt = EO_OPTIONAL_COW_WRITE(parent);
opt->composite_objects = eina_list_prepend(opt->composite_objects, comp_obj_id);
EO_OPTIONAL_COW_END(opt, parent);
if (emb_obj_id) EO_OBJ_DONE(emb_obj_id);
EO_OBJ_DONE(parent_id);
EO_OBJ_DONE(comp_obj_id);
return EINA_TRUE;
err_klass:
if (emb_obj_id) EO_OBJ_DONE(emb_obj_id);
EO_OBJ_DONE(parent_id);
err_parent:
EO_OBJ_DONE(comp_obj_id);
return EINA_FALSE;
}
EOLIAN static Eina_Bool
_efl_object_composite_detach(Eo *parent_id, Efl_Object_Data *pd EINA_UNUSED, Eo *comp_obj_id)
{
Efl_Object_Optional *opt;
EO_OBJ_POINTER_RETURN_VAL(comp_obj_id, comp_obj, EINA_FALSE);
EO_OBJ_POINTER_GOTO(parent_id, parent, err_parent);
// unlikely so improve l1 instr cache by using goto
if (!efl_composite_part_is(comp_obj_id)) goto err_part;
opt = EO_OPTIONAL_COW_WRITE(parent);
opt->composite_objects = eina_list_remove(opt->composite_objects, comp_obj_id);
EO_OPTIONAL_COW_END(opt, parent);
/* Clear the comp parent on the child. */
{
Efl_Object_Data *comp_pd = efl_data_scope_get(comp_obj_id, EFL_OBJECT_CLASS);
comp_pd->ext->composite_parent = NULL;
_efl_object_extension_noneed(comp_pd);
}
EO_OBJ_DONE(parent_id);
EO_OBJ_DONE(comp_obj_id);
return EINA_TRUE;
err_part:
EO_OBJ_DONE(parent_id);
err_parent:
EO_OBJ_DONE(comp_obj_id);
return EINA_FALSE;
}
EOLIAN static Eina_Bool
_efl_object_composite_part_is(Eo *comp_obj_id EINA_UNUSED, Efl_Object_Data *pd)
{
return pd->ext && pd->ext->composite_parent;
}
2013-12-25 06:13:41 -08:00
/* Eo_Dbg */
eo: Rename EAPI macro to EO_API in Eo library Summary: Patch from a series of patches to rename EAPI symbols to specific library DSOs. = The Rationale = This patch is from a series of patches to rename EAPI symbols to specific library DSOs. EAPI was designed to be able to pass `__attribute__ ((visibility ("default")))` for symbols with GCC, which would mean that even if -fvisibility=hidden was used when compiling the library, the needed symbols would get exported. MSVC __almost__ works like GCC (or mingw) in which you can declare everything as export and it will just work (slower, but it will work). But there's a caveat: global variables will not work the same way for MSVC, but works for mingw and GCC. For global variables (as opposed to functions), MSVC requires correct DSO visibility for MSVC: instead of declaring a symbol as export for everything, you need to declare it as import when importing from another DSO and export when defining it locally. With current EAPI definitions, we get the following example working in mingw and MSVC (observe it doesn't define any global variables as exported symbols). Example 1: dll1: ``` EAPI void foo(void); EAPI void bar() { foo(); } ``` dll2: ``` EAPI void foo() { printf ("foo\n"); } ``` This works fine with API defined as __declspec(dllexport) in both cases and for gcc defining as `__atttribute__((visibility("default")))`. However, the following: Example 2: dll1: ``` EAPI extern int foo; EAPI void foobar(void); EAPI void bar() { foo = 5; foobar(); } ``` dll2: ``` EAPI int foo = 0; EAPI void foobar() { printf ("foo %d\n", foo); } ``` This will work on mingw but will not work for MSVC. And that's why LIBAPI is the only solution that works for MSVC. Co-authored-by: João Paulo Taylor Ienczak Zanette <jpaulotiz@gmail.com> Co-authored-by: Lucas Cavalcante de Sousa <lucks.sousa@gmail.com> Co-authored-by: Ricardo Campos <ricardo.campos@expertise.dev> Reviewers: jptiz, lucas, vtorri, woohyun Reviewed By: jptiz, lucas, vtorri Subscribers: cedric, #reviewers, #committers Tags: #efl Differential Revision: https://phab.enlightenment.org/D12203
2020-12-09 08:50:29 -08:00
EO_API void
efl_dbg_info_free(Efl_Dbg_Info *info)
2013-12-25 06:13:41 -08:00
{
eina_value_flush(&(info->value));
eina_freeq_ptr_main_add(info, free, sizeof(*info));
2013-12-25 06:13:41 -08:00
}
static Eina_Bool
_eo_dbg_info_setup(const Eina_Value_Type *type, void *mem)
{
memset(mem, 0, type->value_size);
return EINA_TRUE;
}
static Eina_Bool
_eo_dbg_info_flush(const Eina_Value_Type *type EINA_UNUSED, void *_mem)
{
Efl_Dbg_Info *mem = *(Efl_Dbg_Info **) _mem;
2013-12-25 06:13:41 -08:00
eina_stringshare_del(mem->name);
eina_value_flush(&(mem->value));
eina_freeq_ptr_main_add(mem, free, sizeof(*mem));
2013-12-25 06:13:41 -08:00
return EINA_TRUE;
}
static Eina_Bool
_eo_dbg_info_copy(const Eina_Value_Type *type EINA_UNUSED, const void *_src, void *_dst)
{
const Efl_Dbg_Info **src = (const Efl_Dbg_Info **) _src;
Efl_Dbg_Info **dst = _dst;
*dst = calloc(1, sizeof(Efl_Dbg_Info));
if (!*dst) return EINA_FALSE;
2013-12-25 06:13:41 -08:00
(*dst)->name = eina_stringshare_ref((*src)->name);
eina_value_copy(&((*src)->value), &((*dst)->value));
return EINA_TRUE;
}
static Eina_Bool
_eo_dbg_info_convert_to(const Eina_Value_Type *type EINA_UNUSED, const Eina_Value_Type *convert, const void *type_mem, void *convert_mem)
{
/* FIXME: For the meanwhile, just use the inner type for the value. */
const Efl_Dbg_Info **src = (const Efl_Dbg_Info **) type_mem;
2013-12-25 06:13:41 -08:00
if (convert == EINA_VALUE_TYPE_STRINGSHARE ||
convert == EINA_VALUE_TYPE_STRING)
{
Eina_Bool ret;
const char *other_mem;
char *inner_val = eina_value_to_string(&(*src)->value);
other_mem = inner_val;
ret = eina_value_type_pset(convert, convert_mem, &other_mem);
eina_freeq_ptr_main_add(inner_val, free, 0);
2013-12-25 06:13:41 -08:00
return ret;
}
eina_error_set(EINA_ERROR_VALUE_FAILED);
return EINA_FALSE;
}
static Eina_Bool
_eo_dbg_info_pset(const Eina_Value_Type *type EINA_UNUSED, void *_mem, const void *_ptr)
{
Efl_Dbg_Info **mem = _mem;
if (*mem) free(*mem);
2013-12-25 06:13:41 -08:00
*mem = (void *) _ptr;
return EINA_TRUE;
}
static Eina_Bool
_eo_dbg_info_pget(const Eina_Value_Type *type EINA_UNUSED, const void *_mem, void *_ptr)
{
Efl_Dbg_Info **ptr = _ptr;
2013-12-25 06:13:41 -08:00
*ptr = (void *) _mem;
return EINA_TRUE;
}
static const Eina_Value_Type _EFL_DBG_INFO_TYPE = {
2013-12-25 06:13:41 -08:00
EINA_VALUE_TYPE_VERSION,
sizeof(Efl_Dbg_Info *),
"Efl_Dbg_Info_Ptr",
2013-12-25 06:13:41 -08:00
_eo_dbg_info_setup,
_eo_dbg_info_flush,
_eo_dbg_info_copy,
NULL,
_eo_dbg_info_convert_to,
NULL,
NULL,
_eo_dbg_info_pset,
_eo_dbg_info_pget
};
eo: Rename EAPI macro to EO_API in Eo library Summary: Patch from a series of patches to rename EAPI symbols to specific library DSOs. = The Rationale = This patch is from a series of patches to rename EAPI symbols to specific library DSOs. EAPI was designed to be able to pass `__attribute__ ((visibility ("default")))` for symbols with GCC, which would mean that even if -fvisibility=hidden was used when compiling the library, the needed symbols would get exported. MSVC __almost__ works like GCC (or mingw) in which you can declare everything as export and it will just work (slower, but it will work). But there's a caveat: global variables will not work the same way for MSVC, but works for mingw and GCC. For global variables (as opposed to functions), MSVC requires correct DSO visibility for MSVC: instead of declaring a symbol as export for everything, you need to declare it as import when importing from another DSO and export when defining it locally. With current EAPI definitions, we get the following example working in mingw and MSVC (observe it doesn't define any global variables as exported symbols). Example 1: dll1: ``` EAPI void foo(void); EAPI void bar() { foo(); } ``` dll2: ``` EAPI void foo() { printf ("foo\n"); } ``` This works fine with API defined as __declspec(dllexport) in both cases and for gcc defining as `__atttribute__((visibility("default")))`. However, the following: Example 2: dll1: ``` EAPI extern int foo; EAPI void foobar(void); EAPI void bar() { foo = 5; foobar(); } ``` dll2: ``` EAPI int foo = 0; EAPI void foobar() { printf ("foo %d\n", foo); } ``` This will work on mingw but will not work for MSVC. And that's why LIBAPI is the only solution that works for MSVC. Co-authored-by: João Paulo Taylor Ienczak Zanette <jpaulotiz@gmail.com> Co-authored-by: Lucas Cavalcante de Sousa <lucks.sousa@gmail.com> Co-authored-by: Ricardo Campos <ricardo.campos@expertise.dev> Reviewers: jptiz, lucas, vtorri, woohyun Reviewed By: jptiz, lucas, vtorri Subscribers: cedric, #reviewers, #committers Tags: #efl Differential Revision: https://phab.enlightenment.org/D12203
2020-12-09 08:50:29 -08:00
EO_API const Eina_Value_Type *EFL_DBG_INFO_TYPE = &_EFL_DBG_INFO_TYPE;
2013-12-25 06:13:41 -08:00
/* EOF event callbacks */
/* EFL_OBJECT_CLASS stuff */
#define MY_CLASS EFL_OBJECT_CLASS
2013-12-25 06:13:41 -08:00
static Eina_Value
_efl_future_cb(void *data, const Eina_Value value, const Eina_Future *dead_future)
{
Efl_Future_Pending *pending = data;
Eina_Value ret = value;
const Eo *o;
Efl_Object_Data *pd;
EINA_SAFETY_ON_NULL_GOTO(pending, err);
o = pending->o;
pd = efl_data_scope_get(o, EFL_OBJECT_CLASS);
EINA_SAFETY_ON_NULL_GOTO(pd, err);
pd->pending_futures = eina_inlist_remove(pd->pending_futures,
EINA_INLIST_GET(pending));
efl_ref(o);
EASY_FUTURE_DISPATCH(ret, value, dead_future, &pending->desc, (void*) o, (void*) pending->desc.data);
efl_unref(o);
_efl_pending_future_free(pending);
return ret;
err:
eina_value_setup(&ret, EINA_VALUE_TYPE_ERROR);
eina_value_set(&ret, ENOMEM);
return ret;
}
eo: Rename EAPI macro to EO_API in Eo library Summary: Patch from a series of patches to rename EAPI symbols to specific library DSOs. = The Rationale = This patch is from a series of patches to rename EAPI symbols to specific library DSOs. EAPI was designed to be able to pass `__attribute__ ((visibility ("default")))` for symbols with GCC, which would mean that even if -fvisibility=hidden was used when compiling the library, the needed symbols would get exported. MSVC __almost__ works like GCC (or mingw) in which you can declare everything as export and it will just work (slower, but it will work). But there's a caveat: global variables will not work the same way for MSVC, but works for mingw and GCC. For global variables (as opposed to functions), MSVC requires correct DSO visibility for MSVC: instead of declaring a symbol as export for everything, you need to declare it as import when importing from another DSO and export when defining it locally. With current EAPI definitions, we get the following example working in mingw and MSVC (observe it doesn't define any global variables as exported symbols). Example 1: dll1: ``` EAPI void foo(void); EAPI void bar() { foo(); } ``` dll2: ``` EAPI void foo() { printf ("foo\n"); } ``` This works fine with API defined as __declspec(dllexport) in both cases and for gcc defining as `__atttribute__((visibility("default")))`. However, the following: Example 2: dll1: ``` EAPI extern int foo; EAPI void foobar(void); EAPI void bar() { foo = 5; foobar(); } ``` dll2: ``` EAPI int foo = 0; EAPI void foobar() { printf ("foo %d\n", foo); } ``` This will work on mingw but will not work for MSVC. And that's why LIBAPI is the only solution that works for MSVC. Co-authored-by: João Paulo Taylor Ienczak Zanette <jpaulotiz@gmail.com> Co-authored-by: Lucas Cavalcante de Sousa <lucks.sousa@gmail.com> Co-authored-by: Ricardo Campos <ricardo.campos@expertise.dev> Reviewers: jptiz, lucas, vtorri, woohyun Reviewed By: jptiz, lucas, vtorri Subscribers: cedric, #reviewers, #committers Tags: #efl Differential Revision: https://phab.enlightenment.org/D12203
2020-12-09 08:50:29 -08:00
EO_API Eina_Future_Desc
efl_future_cb_from_desc(const Eo *o, const Efl_Future_Cb_Desc desc)
{
Efl_Future_Pending *pending = NULL;
Eina_Future **storage = NULL;
Efl_Object_Data *pd;
Eina_Bool invalidate;
EINA_SAFETY_ON_NULL_GOTO(o, end);
pd = efl_data_scope_get(o, EFL_OBJECT_CLASS);
EINA_SAFETY_ON_NULL_GOTO(pd, end);
EO_OBJ_POINTER_GOTO(o, eo_obj, end);
invalidate = eo_obj->invalidate;
EO_OBJ_DONE(o);
EINA_SAFETY_ON_TRUE_GOTO(invalidate, end);
pending = _efl_pending_future_new();
EINA_SAFETY_ON_NULL_GOTO(pending, end);
memcpy(&pending->desc, &desc, sizeof(Efl_Future_Cb_Desc));
pending->o = o;
pending->future = NULL;
if (!pending->desc.storage) pending->desc.storage = &pending->future;
pd->pending_futures = eina_inlist_append(pd->pending_futures,
EINA_INLIST_GET(pending));
storage = pending->desc.storage;
end:
return (Eina_Future_Desc){ .cb = _efl_future_cb, .data = pending, .storage = storage };
}
eo: Rename EAPI macro to EO_API in Eo library Summary: Patch from a series of patches to rename EAPI symbols to specific library DSOs. = The Rationale = This patch is from a series of patches to rename EAPI symbols to specific library DSOs. EAPI was designed to be able to pass `__attribute__ ((visibility ("default")))` for symbols with GCC, which would mean that even if -fvisibility=hidden was used when compiling the library, the needed symbols would get exported. MSVC __almost__ works like GCC (or mingw) in which you can declare everything as export and it will just work (slower, but it will work). But there's a caveat: global variables will not work the same way for MSVC, but works for mingw and GCC. For global variables (as opposed to functions), MSVC requires correct DSO visibility for MSVC: instead of declaring a symbol as export for everything, you need to declare it as import when importing from another DSO and export when defining it locally. With current EAPI definitions, we get the following example working in mingw and MSVC (observe it doesn't define any global variables as exported symbols). Example 1: dll1: ``` EAPI void foo(void); EAPI void bar() { foo(); } ``` dll2: ``` EAPI void foo() { printf ("foo\n"); } ``` This works fine with API defined as __declspec(dllexport) in both cases and for gcc defining as `__atttribute__((visibility("default")))`. However, the following: Example 2: dll1: ``` EAPI extern int foo; EAPI void foobar(void); EAPI void bar() { foo = 5; foobar(); } ``` dll2: ``` EAPI int foo = 0; EAPI void foobar() { printf ("foo %d\n", foo); } ``` This will work on mingw but will not work for MSVC. And that's why LIBAPI is the only solution that works for MSVC. Co-authored-by: João Paulo Taylor Ienczak Zanette <jpaulotiz@gmail.com> Co-authored-by: Lucas Cavalcante de Sousa <lucks.sousa@gmail.com> Co-authored-by: Ricardo Campos <ricardo.campos@expertise.dev> Reviewers: jptiz, lucas, vtorri, woohyun Reviewed By: jptiz, lucas, vtorri Subscribers: cedric, #reviewers, #committers Tags: #efl Differential Revision: https://phab.enlightenment.org/D12203
2020-12-09 08:50:29 -08:00
EO_API Eina_Future *
efl_future_chain_array(Eo *obj,
Eina_Future *prev,
const Efl_Future_Cb_Desc descs[])
{
ssize_t i = -1;
Eina_Future *f = prev;
for (i = 0; descs[i].success || descs[i].error || descs[i].free || descs[i].success_type; i++)
{
Eina_Future_Desc eina_desc = efl_future_cb_from_desc(obj, descs[i]);
f = eina_future_then_from_desc(f, eina_desc);
EINA_SAFETY_ON_NULL_GOTO(f, err);
}
return f;
err:
/*
There's no need to cancel the futures, since eina_future_then_from_desc()
will cancel the whole chain in case of failure.
All we need to do is to free the remaining descs
*/
for (i = i + 1; descs[i].error || descs[i].free; i++)
{
if (descs[i].error)
{
Eina_Value r = descs[i].error(obj, (void*) descs[i].data, ENOMEM);
eina_value_flush(&r);
}
if (descs[i].free) descs[i].free(obj, (void*) descs[i].data, NULL);
}
return NULL;
}
EOLIAN static Eo *
_efl_object_constructor(Eo *obj, Efl_Object_Data *pd EINA_UNUSED)
2013-12-25 06:13:41 -08:00
{
DBG("%p - %s.", obj, efl_class_name_get(obj));
2013-12-25 06:13:41 -08:00
_eo_condtor_done(obj);
return obj;
2013-12-25 06:13:41 -08:00
}
EOLIAN static void
_efl_object_destructor(Eo *obj, Efl_Object_Data *pd)
2013-12-25 06:13:41 -08:00
{
_Eo_Object *obj_child;
Eina_Inlist *l;
Efl_Object_Extension *ext;
_Eo_Object *obj_data2 = NULL;
DBG("%p - %s.", obj, efl_class_name_get(obj));
2013-12-25 06:13:41 -08:00
// special removal - remove from children list by hand after getting
// child handle in case unparent method is overridden and does
// extra things like removes other children too later on in the list
// this is a goto because more often than not objects do not have children
// so it's unlikely they will need the child cleanup code to so to have
// better l1 cache instruction coherency, move this to the end
if (pd->children) goto children;
children_back:
// If we are a composite object, detach children. it is quite unlikely
// we are a composite object, so put the core of this handling
// at the end out of l1 cache prefetch
{
EO_OBJ_POINTER_RETURN(obj, obj_data);
obj_data2 = obj_data;
if (obj_data->opt->composite_objects) goto composite_obj;
composite_obj_back:
EO_OBJ_DONE(obj);
}
if (pd->ext && pd->ext->composite_parent)
efl_composite_detach(pd->ext->composite_parent, obj);
// parent still being here is unlikely, so move error handling out of the
// code execution path
if (pd->parent) goto err_parent;
err_parent_back:
// this isn't 100% correct, as the object is still "slightly" alive at this
// point (so efl_destructed_is() returns false), but triggering the
// "destruct" event here is the simplest, safest solution.
if (EINA_UNLIKELY(pd->event_cb_EFL_EVENT_DESTRUCT))
_event_callback_call(obj, pd, EFL_EVENT_DESTRUCT, NULL, EINA_FALSE);
// remove generic data after this final event, in case they are used in a cb
_eo_generic_data_del_all(obj, pd);
_eo_callback_remove_all(pd);
2013-12-25 06:13:41 -08:00
_wref_destruct(pd);
ext = pd->ext;
// it is rather likely we dont have any extension section for most objects
// so return immediately here to avoid pulling in more instructions to
// the 1l cache if we can
if (!ext)
{
_eo_condtor_done(obj);
return;
}
eina_stringshare_del(ext->name);
ext->name = NULL;
eina_stringshare_del(ext->comment);
ext->comment = NULL;
_efl_object_extension_noneed(pd);
_eo_condtor_done(obj);
return;
children:
ERR("Object %p of type '%s' is still holding child at time of destruction.\n",
obj, efl_class_name_get(obj));
EINA_INLIST_FOREACH_SAFE(pd->children, l, obj_child)
{
Eo *child;
child = _eo_obj_id_get(obj_child);
efl_parent_set(child, NULL);
}
goto children_back;
composite_obj:
{
Eina_List *itr, *next;
Eo *emb_obj_id;
EINA_LIST_FOREACH_SAFE(obj_data2->opt->composite_objects, itr, next, emb_obj_id)
{
efl_composite_detach(obj, emb_obj_id);
}
}
goto composite_obj_back;
err_parent:
if (EINA_LIKELY(!pd->allow_parent_unref))
ERR("Object '%p' of type '%s' still has a parent at the time of destruction.", obj, efl_class_name_get(obj));
efl_parent_set(obj, NULL);
goto err_parent_back;
2013-12-25 06:13:41 -08:00
}
EOLIAN static void
_efl_object_allow_parent_unref_set(Eo *obj_id, Efl_Object_Data *pd, Eina_Bool allow)
{
EO_OBJ_POINTER_RETURN(obj_id, obj);
obj->allow_parent_unref = !!allow;
pd->allow_parent_unref = !!allow;
EO_OBJ_DONE(obj_id);
}
EOLIAN static Eina_Bool
_efl_object_allow_parent_unref_get(const Eo *obj_id EINA_UNUSED, Efl_Object_Data *pd)
{
return pd->allow_parent_unref;
}
eo: Rename EAPI macro to EO_API in Eo library Summary: Patch from a series of patches to rename EAPI symbols to specific library DSOs. = The Rationale = This patch is from a series of patches to rename EAPI symbols to specific library DSOs. EAPI was designed to be able to pass `__attribute__ ((visibility ("default")))` for symbols with GCC, which would mean that even if -fvisibility=hidden was used when compiling the library, the needed symbols would get exported. MSVC __almost__ works like GCC (or mingw) in which you can declare everything as export and it will just work (slower, but it will work). But there's a caveat: global variables will not work the same way for MSVC, but works for mingw and GCC. For global variables (as opposed to functions), MSVC requires correct DSO visibility for MSVC: instead of declaring a symbol as export for everything, you need to declare it as import when importing from another DSO and export when defining it locally. With current EAPI definitions, we get the following example working in mingw and MSVC (observe it doesn't define any global variables as exported symbols). Example 1: dll1: ``` EAPI void foo(void); EAPI void bar() { foo(); } ``` dll2: ``` EAPI void foo() { printf ("foo\n"); } ``` This works fine with API defined as __declspec(dllexport) in both cases and for gcc defining as `__atttribute__((visibility("default")))`. However, the following: Example 2: dll1: ``` EAPI extern int foo; EAPI void foobar(void); EAPI void bar() { foo = 5; foobar(); } ``` dll2: ``` EAPI int foo = 0; EAPI void foobar() { printf ("foo %d\n", foo); } ``` This will work on mingw but will not work for MSVC. And that's why LIBAPI is the only solution that works for MSVC. Co-authored-by: João Paulo Taylor Ienczak Zanette <jpaulotiz@gmail.com> Co-authored-by: Lucas Cavalcante de Sousa <lucks.sousa@gmail.com> Co-authored-by: Ricardo Campos <ricardo.campos@expertise.dev> Reviewers: jptiz, lucas, vtorri, woohyun Reviewed By: jptiz, lucas, vtorri Subscribers: cedric, #reviewers, #committers Tags: #efl Differential Revision: https://phab.enlightenment.org/D12203
2020-12-09 08:50:29 -08:00
EO_API void
___efl_auto_unref_set(Eo *obj_id, Eina_Bool enable)
eo: Add beta API for auto_unref after a call Before screaming in horror (C++...) here's why we may need this: Efl.Part.part API returns an object that is by definition valid for a single function call only. Enforcing this in practice is actually quite hard as all implementation functions must manually take care of the life-cycle. This is a lot of code in many places and a lot of opportunities to forget to properly handle that life-cycle. Also, this means any invalid function call on a part will leak an object. This API absolutely must remain either "internal" or "beta" and definitely not become abused by applications. On top of that such an API can cause great trouble for bindings like C++. As a consequence, only specially crafted APIs like efl_part() should return an object marked as auto_unref. Alternatively this API could be defined in Eo.h or some other Eo_Internal.h. I placed it in efl_object.eo because it's much more convenient :) (read: I'm lazy) **** Performance notes: Tested with clang & gcc (with -O2), I had a look at the output of perf top, in particular the asm view. I used eo_bench in a loop. My conclusions are: - EINA_LIKELY/UNLIKELY actually works. The jump statement varies according to the expectation. I highly doubt all those ugly goto in eo.c / Eo.h are even useful. - The impact of auto_unref on a call_resolve is so small it doesn't even appear in the trace. It is significant inside call_end, though (obviously, that function is just a few lines long). That function accounts for ~1% to ~4% of all CPU time. The impact of auto_unref in call_end is ~4% of the function time. This means ~0.16% of all CPU time (worst measured case). _efl_object_op_api_id_get simply doesn't show up because of caching, so the extra check there is negligible. PS: I also tested EINA_LIKELY/UNLIKELY by compiling with -O2 and looking at the output with objdump. The flag is well respected, and the jump instructions are what you would expect (no jump for LIKELY and jump for UNLIKELY). Conclusion: The goto's in eo.c only make the code harder to read...
2017-10-13 01:18:41 -07:00
{
// Write-only property
EO_OBJ_POINTER_RETURN(obj_id, obj);
obj->auto_unref = enable ? 1 : 0;
EO_OBJ_DONE(obj_id);
eo: Add beta API for auto_unref after a call Before screaming in horror (C++...) here's why we may need this: Efl.Part.part API returns an object that is by definition valid for a single function call only. Enforcing this in practice is actually quite hard as all implementation functions must manually take care of the life-cycle. This is a lot of code in many places and a lot of opportunities to forget to properly handle that life-cycle. Also, this means any invalid function call on a part will leak an object. This API absolutely must remain either "internal" or "beta" and definitely not become abused by applications. On top of that such an API can cause great trouble for bindings like C++. As a consequence, only specially crafted APIs like efl_part() should return an object marked as auto_unref. Alternatively this API could be defined in Eo.h or some other Eo_Internal.h. I placed it in efl_object.eo because it's much more convenient :) (read: I'm lazy) **** Performance notes: Tested with clang & gcc (with -O2), I had a look at the output of perf top, in particular the asm view. I used eo_bench in a loop. My conclusions are: - EINA_LIKELY/UNLIKELY actually works. The jump statement varies according to the expectation. I highly doubt all those ugly goto in eo.c / Eo.h are even useful. - The impact of auto_unref on a call_resolve is so small it doesn't even appear in the trace. It is significant inside call_end, though (obviously, that function is just a few lines long). That function accounts for ~1% to ~4% of all CPU time. The impact of auto_unref in call_end is ~4% of the function time. This means ~0.16% of all CPU time (worst measured case). _efl_object_op_api_id_get simply doesn't show up because of caching, so the extra check there is negligible. PS: I also tested EINA_LIKELY/UNLIKELY by compiling with -O2 and looking at the output with objdump. The flag is well respected, and the jump instructions are what you would expect (no jump for LIKELY and jump for UNLIKELY). Conclusion: The goto's in eo.c only make the code harder to read...
2017-10-13 01:18:41 -07:00
}
EOLIAN static Eo *
_efl_object_finalize(Eo *obj, Efl_Object_Data *pd EINA_UNUSED)
{
return obj;
}
EOLIAN static void
_efl_object_class_constructor(Efl_Class *klass EINA_UNUSED)
2013-12-25 06:13:41 -08:00
{
event_freeze_count = 0;
_legacy_events_hash = eina_hash_stringshared_new(_legacy_events_hash_free_cb);
_eo_callback_mempool =
eina_mempool_add("chained_mempool", NULL, NULL,
sizeof(Eo_Callback_Description), 256);
_efl_pending_future_mempool =
eina_mempool_add("chained_mempool", NULL, NULL,
sizeof(Efl_Future_Pending), 256);
_efl_future_scheduler_entry_mempool =
eina_mempool_add("chained_mempool", NULL, NULL,
sizeof(Efl_Future_Scheduler_Entry), 256);
_eo_nostep_alloc = !!getenv("EO_NOSTEP_ALLOC");
}
EOLIAN static void
_efl_object_class_destructor(Efl_Class *klass EINA_UNUSED)
{
eina_mempool_del(_efl_future_scheduler_entry_mempool);
eina_mempool_del(_efl_pending_future_mempool);
eina_mempool_del(_eo_callback_mempool);
eina_hash_free(_legacy_events_hash);
2013-12-25 06:13:41 -08:00
}
#define EFL_OBJECT_EXTRA_OPS \
EFL_OBJECT_OP_FUNC(efl_event_callback_priority_add, _efl_object_event_callback_priority_add), \
EFL_OBJECT_OP_FUNC(efl_event_callback_del, _efl_object_event_callback_del), \
EFL_OBJECT_OP_FUNC(efl_event_callback_array_priority_add, _efl_object_event_callback_array_priority_add), \
EFL_OBJECT_OP_FUNC(efl_event_callback_array_del, _efl_object_event_callback_array_del), \
EFL_OBJECT_OP_FUNC(efl_event_callback_call, _efl_object_event_callback_call), \
EFL_OBJECT_OP_FUNC(efl_event_callback_legacy_call, _efl_object_event_callback_legacy_call), \
EFL_OBJECT_OP_FUNC(efl_event_future_scheduler_get, _efl_object_event_future_scheduler_get), \
EFL_OBJECT_OP_FUNC(efl_event_callback_count, _efl_object_event_callback_count), \
2017-04-26 05:25:37 -07:00
EFL_OBJECT_OP_FUNC(efl_dbg_info_get, _efl_object_dbg_info_get), \
2017-04-26 06:01:44 -07:00
EFL_OBJECT_OP_FUNC(efl_wref_add, _efl_object_wref_add), \
2017-04-26 07:18:49 -07:00
EFL_OBJECT_OP_FUNC(efl_wref_del, _efl_object_wref_del), \
EFL_OBJECT_OP_FUNC(efl_key_data_set, _efl_object_key_data_set), \
EFL_OBJECT_OP_FUNC(efl_key_data_get, _efl_object_key_data_get), \
EFL_OBJECT_OP_FUNC(efl_key_ref_set, _efl_object_key_ref_set), \
EFL_OBJECT_OP_FUNC(efl_key_ref_get, _efl_object_key_ref_get), \
EFL_OBJECT_OP_FUNC(efl_key_wref_set, _efl_object_key_wref_set), \
EFL_OBJECT_OP_FUNC(efl_key_wref_get, _efl_object_key_wref_get), \
EFL_OBJECT_OP_FUNC(efl_key_value_set, _efl_object_key_value_set), \
EFL_OBJECT_OP_FUNC(efl_key_value_get, _efl_object_key_value_get) \
#include "efl_object.eo.c"