forked from enlightenment/efl
ecore - a different take on efl.app class as a super class to efl.loop
so the MAIN loop is actually an efl.app object. which inherits from efl.loop. the idea is that other loops in threads will not be efl.app objects. thread on the creator side return an efl.thread object. inside the thread, like the mainloop, there is now an efl.appthread object that is for all non-main-loop threads. every thread (main loop or child) when it spawns a thread is the parent. there are i/o pipes from parnet to child and back. so parents are generally expected to, if they want to talk to child thread, so use the efl.io interfaces on efl.thread, and the main loop's elf.app class allows you to talk to stdio back to the parent process like the efl.appthread does the same using the efl.io interfaces to talk to its parent app or appthread. it's symmetrical no tests here - sure. i have been holding off on tests until things settle. that's why i haven't done them yet. those will come back in a subsequent commit for really quick examples on using this see: https://phab.enlightenment.org/F2983118 https://phab.enlightenment.org/F2983142 they are just my test code for this. Please see this design document: https://phab.enlightenment.org/w/efl-loops-threads/
This commit is contained in:
parent
1c74aaa7e9
commit
1bdd9e4dd1
|
@ -8,6 +8,7 @@ ecore_eolian_files_legacy = \
|
|||
lib/ecore/efl_loop_timer.eo
|
||||
|
||||
ecore_eolian_files_public = \
|
||||
lib/ecore/efl_app.eo \
|
||||
lib/ecore/efl_loop.eo \
|
||||
lib/ecore/efl_loop_consumer.eo \
|
||||
lib/ecore/efl_loop_fd.eo \
|
||||
|
@ -16,6 +17,8 @@ ecore_eolian_files_public = \
|
|||
lib/ecore/efl_loop_message_handler.eo \
|
||||
lib/ecore/efl_exe.eo \
|
||||
lib/ecore/efl_thread.eo \
|
||||
lib/ecore/efl_appthread.eo \
|
||||
lib/ecore/efl_task.eo \
|
||||
lib/ecore/efl_io_closer_fd.eo \
|
||||
lib/ecore/efl_io_positioner_fd.eo \
|
||||
lib/ecore/efl_io_reader_fd.eo \
|
||||
|
@ -35,8 +38,7 @@ ecore_eolian_files_public = \
|
|||
lib/ecore/efl_interpolator_divisor.eo \
|
||||
lib/ecore/efl_interpolator_bounce.eo \
|
||||
lib/ecore/efl_interpolator_spring.eo \
|
||||
lib/ecore/efl_interpolator_cubic_bezier.eo \
|
||||
lib/ecore/efl_task.eo
|
||||
lib/ecore/efl_interpolator_cubic_bezier.eo
|
||||
|
||||
ecore_eolian_files = \
|
||||
$(ecore_eolian_files_public) \
|
||||
|
@ -95,6 +97,7 @@ lib/ecore/ecore_job.c \
|
|||
lib/ecore/ecore_main.c \
|
||||
lib/ecore/ecore_event_message.c \
|
||||
lib/ecore/ecore_event_message_handler.c \
|
||||
lib/ecore/efl_app.c \
|
||||
lib/ecore/efl_loop.c \
|
||||
lib/ecore/efl_loop_consumer.c \
|
||||
lib/ecore/efl_loop_fd.c \
|
||||
|
@ -134,6 +137,8 @@ lib/ecore/efl_interpolator_spring.c \
|
|||
lib/ecore/efl_interpolator_cubic_bezier.c \
|
||||
lib/ecore/efl_task.c \
|
||||
lib/ecore/efl_exe.c \
|
||||
lib/ecore/efl_thread.c \
|
||||
lib/ecore/efl_appthread.c \
|
||||
lib/ecore/ecore_main_timechanges.c \
|
||||
lib/ecore/ecore_pipe.c \
|
||||
lib/ecore/ecore_poller.c \
|
||||
|
|
|
@ -45,9 +45,12 @@
|
|||
#include "efl_loop_message_handler.eo.h"
|
||||
|
||||
#include "efl_task.eo.h"
|
||||
#include "efl_thread.eo.h"
|
||||
#include "efl_exe.eo.h"
|
||||
|
||||
#include "efl_loop.eo.h"
|
||||
#include "efl_app.eo.h"
|
||||
#include "efl_appthread.eo.h"
|
||||
|
||||
/**
|
||||
* @brief Quits the main loop once all the events currently on the queue have
|
||||
|
@ -103,6 +106,7 @@ EAPI Eina_Promise *efl_loop_promise_new(const Eo *obj, Eina_Promise_Cancel_Cb ca
|
|||
|
||||
/* We ue the factory pattern here, so you shouldn't call eo_add directly. */
|
||||
EAPI Eo *efl_main_loop_get(void);
|
||||
EAPI Eo *efl_app_get(void);
|
||||
|
||||
typedef struct _Efl_Future_Composite_Progress Efl_Future_All_Progress;
|
||||
|
||||
|
|
|
@ -215,8 +215,7 @@ _efl_first_loop_iterate(void *data, const Efl_Event *event)
|
|||
case 'T': fprintf(stderr, "Loop started: '%f' - '%f' = '%f' sec\n", end, _efl_startup_time, end - _efl_startup_time);
|
||||
break;
|
||||
}
|
||||
|
||||
efl_event_callback_del(event->object, EFL_LOOP_EVENT_RESUME,
|
||||
efl_event_callback_del(event->object, EFL_APP_EVENT_RESUME,
|
||||
_efl_first_loop_iterate, data);
|
||||
}
|
||||
|
||||
|
@ -345,13 +344,11 @@ ecore_init(void)
|
|||
|
||||
if (!_no_system_modules)
|
||||
ecore_system_modules_load();
|
||||
|
||||
if (getenv("EFL_FIRST_LOOP"))
|
||||
efl_event_callback_add(efl_main_loop_get(),
|
||||
EFL_LOOP_EVENT_RESUME,
|
||||
EFL_APP_EVENT_RESUME,
|
||||
_efl_first_loop_iterate,
|
||||
getenv("EFL_FIRST_LOOP"));
|
||||
|
||||
_ecore_init_count_threshold = _ecore_init_count;
|
||||
|
||||
eina_log_timing(_ecore_log_dom,
|
||||
|
@ -390,8 +387,7 @@ ecore_shutdown(void)
|
|||
}
|
||||
if (_ecore_init_count-- != _ecore_init_count_threshold)
|
||||
goto end;
|
||||
|
||||
efl_event_callback_call(efl_main_loop_get(), EFL_LOOP_EVENT_TERMINATE, NULL);
|
||||
efl_event_callback_call(efl_main_loop_get(), EFL_APP_EVENT_TERMINATE, NULL);
|
||||
|
||||
ecore_system_modules_unload();
|
||||
|
||||
|
|
|
@ -66,7 +66,7 @@ ecore_exe_pipe_run(const char *exe_cmd,
|
|||
const void *data)
|
||||
{
|
||||
EINA_MAIN_LOOP_CHECK_RETURN_VAL(NULL);
|
||||
Ecore_Exe *ret = efl_add(MY_CLASS, efl_loop_main_get(EFL_LOOP_CLASS),
|
||||
Ecore_Exe *ret = efl_add(MY_CLASS, efl_main_loop_get(),
|
||||
ecore_obj_exe_command_set(efl_added, exe_cmd,
|
||||
flags));
|
||||
if (ret)
|
||||
|
|
|
@ -1372,7 +1372,7 @@ ecore_main_fd_handler_add(int fd,
|
|||
{
|
||||
Ecore_Fd_Handler *fdh = NULL;
|
||||
EINA_MAIN_LOOP_CHECK_RETURN_VAL(NULL);
|
||||
fdh = _ecore_main_fd_handler_add(efl_loop_main_get(EFL_LOOP_CLASS),
|
||||
fdh = _ecore_main_fd_handler_add(efl_main_loop_get(),
|
||||
ML_DAT, NULL, fd, flags, func, data,
|
||||
buf_func, buf_data, EINA_FALSE);
|
||||
if (fdh) fdh->legacy = EINA_TRUE;
|
||||
|
@ -1388,7 +1388,7 @@ ecore_main_fd_handler_file_add(int fd,
|
|||
const void *buf_data)
|
||||
{
|
||||
EINA_MAIN_LOOP_CHECK_RETURN_VAL(NULL);
|
||||
return _ecore_main_fd_handler_add(efl_loop_main_get(EFL_LOOP_CLASS),
|
||||
return _ecore_main_fd_handler_add(efl_main_loop_get(),
|
||||
ML_DAT, NULL, fd, flags, func, data,
|
||||
buf_func, buf_data, EINA_TRUE);
|
||||
}
|
||||
|
@ -1595,7 +1595,7 @@ ecore_main_fd_handler_active_set(Ecore_Fd_Handler *fd_handler,
|
|||
}
|
||||
|
||||
void
|
||||
_ecore_main_content_clear(Efl_Loop_Data *pd)
|
||||
_ecore_main_content_clear(Eo *obj, Efl_Loop_Data *pd)
|
||||
{
|
||||
Efl_Promise *promise;
|
||||
Efl_Future *future;
|
||||
|
@ -1608,7 +1608,7 @@ _ecore_main_content_clear(Efl_Loop_Data *pd)
|
|||
ecore_loop_promise_fulfill(promise);
|
||||
|
||||
// FIXME
|
||||
__eina_promise_cancel_all();
|
||||
__eina_promise_cancel_data(obj);
|
||||
|
||||
while (pd->fd_handlers)
|
||||
{
|
||||
|
|
|
@ -88,6 +88,7 @@ typedef struct _Efl_Loop_Future_Scheduler Efl_Loop_Future_Scheduler;
|
|||
typedef struct _Efl_Loop_Data Efl_Loop_Data;
|
||||
|
||||
typedef struct _Efl_Task_Data Efl_Task_Data;
|
||||
typedef struct _Efl_Appthread_Data Efl_Appthread_Data;
|
||||
|
||||
typedef struct _Message_Handler Message_Handler;
|
||||
typedef struct _Message Message;
|
||||
|
@ -193,6 +194,18 @@ struct _Efl_Task_Data
|
|||
Eina_Bool exited : 1;
|
||||
};
|
||||
|
||||
struct _Efl_Appthread_Data
|
||||
{
|
||||
struct {
|
||||
int in, out;
|
||||
Eo *in_handler, *out_handler;
|
||||
Eina_Bool can_read : 1;
|
||||
Eina_Bool eos_read : 1;
|
||||
Eina_Bool can_write : 1;
|
||||
} fd, ctrl;
|
||||
int read_listeners;
|
||||
};
|
||||
|
||||
|
||||
#define EVAS_FRAME_QUEUING 1 /* for test */
|
||||
|
||||
|
@ -325,7 +338,7 @@ _ecore_main_win32_handler_del(Eo *obj,
|
|||
Efl_Loop_Data *pd,
|
||||
Ecore_Win32_Handler *win32_handler);
|
||||
|
||||
void _ecore_main_content_clear(Efl_Loop_Data *pd);
|
||||
void _ecore_main_content_clear(Eo *obj, Efl_Loop_Data *pd);
|
||||
void _ecore_main_shutdown(void);
|
||||
|
||||
#if defined (_WIN32) || defined (__lv2ppu__) || defined (HAVE_EXOTIC)
|
||||
|
@ -525,7 +538,7 @@ void ecore_loop_promise_fulfill(Efl_Promise *p);
|
|||
// access to direct input cb
|
||||
#define ECORE_EVAS_INTERNAL
|
||||
|
||||
#define EFL_LOOP_DATA efl_data_scope_get(efl_loop_main_get(EFL_LOOP_CLASS), EFL_LOOP_CLASS)
|
||||
#define EFL_LOOP_DATA efl_data_scope_get(efl_main_loop_get(), EFL_LOOP_CLASS)
|
||||
|
||||
EOAPI Eina_Bool efl_loop_message_process(Eo *obj);
|
||||
|
||||
|
|
|
@ -78,9 +78,9 @@ _ecore_signal_pipe_read(Eo *obj)
|
|||
if (loop)
|
||||
{
|
||||
if (sdata.sig == SIGUSR1)
|
||||
efl_event_callback_call(loop, EFL_LOOP_EVENT_SIGNAL_USR1, NULL);
|
||||
efl_event_callback_call(loop, EFL_APP_EVENT_SIGNAL_USR1, NULL);
|
||||
else
|
||||
efl_event_callback_call(loop, EFL_LOOP_EVENT_SIGNAL_USR2, NULL);
|
||||
efl_event_callback_call(loop, EFL_APP_EVENT_SIGNAL_USR2, NULL);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
@ -95,7 +95,7 @@ _ecore_signal_pipe_read(Eo *obj)
|
|||
}
|
||||
Eo *loop = efl_provider_find(obj, EFL_LOOP_CLASS);
|
||||
if (loop)
|
||||
efl_event_callback_call(loop, EFL_LOOP_EVENT_SIGNAL_HUP, NULL);
|
||||
efl_event_callback_call(loop, EFL_APP_EVENT_SIGNAL_HUP, NULL);
|
||||
}
|
||||
break;
|
||||
case SIGQUIT:
|
||||
|
@ -112,6 +112,9 @@ _ecore_signal_pipe_read(Eo *obj)
|
|||
ecore_event_add(ECORE_EVENT_SIGNAL_EXIT, e,
|
||||
_ecore_signal_generic_free, NULL);
|
||||
}
|
||||
Eo *loop = efl_provider_find(obj, EFL_LOOP_CLASS);
|
||||
if (loop)
|
||||
efl_event_callback_call(loop, EFL_TASK_EVENT_EXIT, NULL);
|
||||
}
|
||||
break;
|
||||
#ifdef SIGPWR
|
||||
|
|
|
@ -74,7 +74,7 @@ static void
|
|||
_check_timer_event_catcher_add(void *data, const Efl_Event *event)
|
||||
{
|
||||
Efl_Loop_Timer_Data *timer = data;
|
||||
const Efl_Callback_Array_Item *array = event->info;
|
||||
const Efl_Callback_Array_Item_Full *array = event->info;
|
||||
int i;
|
||||
|
||||
for (i = 0; array[i].desc != NULL; i++)
|
||||
|
@ -94,7 +94,7 @@ static void
|
|||
_check_timer_event_catcher_del(void *data, const Efl_Event *event)
|
||||
{
|
||||
Efl_Loop_Timer_Data *timer = data;
|
||||
const Efl_Callback_Array_Item *array = event->info;
|
||||
const Efl_Callback_Array_Item_Full *array = event->info;
|
||||
int i;
|
||||
|
||||
for (i = 0; array[i].desc != NULL; i++)
|
||||
|
|
|
@ -0,0 +1,415 @@
|
|||
#ifdef HAVE_CONFIG_H
|
||||
# include <config.h>
|
||||
#endif
|
||||
|
||||
#define EFL_IO_READER_PROTECTED 1
|
||||
#define EFL_IO_WRITER_PROTECTED 1
|
||||
#define EFL_IO_CLOSER_PROTECTED 1
|
||||
|
||||
#include <Ecore.h>
|
||||
|
||||
#include "ecore_private.h"
|
||||
|
||||
#ifndef _WIN32
|
||||
# include <sys/resource.h>
|
||||
#endif
|
||||
|
||||
#define MY_CLASS EFL_APP_CLASS
|
||||
|
||||
typedef struct _Efl_App_Data Efl_App_Data;
|
||||
|
||||
struct _Efl_App_Data
|
||||
{
|
||||
struct {
|
||||
int in, out;
|
||||
Eo *in_handler, *out_handler;
|
||||
Eina_Bool can_read : 1;
|
||||
Eina_Bool eos_read : 1;
|
||||
Eina_Bool can_write : 1;
|
||||
} fd;
|
||||
int read_listeners;
|
||||
};
|
||||
|
||||
Efl_Version _app_efl_version = { 0, 0, 0, 0, NULL, NULL };
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
EAPI Eo *
|
||||
efl_app_get(void)
|
||||
{
|
||||
return efl_main_loop_get();
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static void
|
||||
_parent_read_listeners_modify(Efl_App_Data *pd, int mod)
|
||||
{
|
||||
pd->read_listeners += mod;
|
||||
|
||||
if (pd->fd.out_handler)
|
||||
{
|
||||
if ((pd->read_listeners == 0) && (mod < 0))
|
||||
efl_loop_handler_active_set
|
||||
(pd->fd.out_handler, EFL_LOOP_HANDLER_FLAGS_NONE);
|
||||
else if ((pd->read_listeners == 1) && (mod > 0))
|
||||
efl_loop_handler_active_set
|
||||
(pd->fd.out_handler, EFL_LOOP_HANDLER_FLAGS_READ);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
_cb_event_callback_add(void *data, const Efl_Event *event)
|
||||
{
|
||||
Efl_App_Data *pd = data;
|
||||
const Efl_Callback_Array_Item_Full *array = event->info;
|
||||
int i;
|
||||
|
||||
for (i = 0; array[i].desc != NULL; i++)
|
||||
{
|
||||
if (array[i].desc == EFL_IO_READER_EVENT_CAN_READ_CHANGED)
|
||||
_parent_read_listeners_modify(pd, 1);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
_cb_event_callback_del(void *data, const Efl_Event *event)
|
||||
{
|
||||
Efl_App_Data *pd = data;
|
||||
const Efl_Callback_Array_Item_Full *array = event->info;
|
||||
int i;
|
||||
|
||||
for (i = 0; array[i].desc != NULL; i++)
|
||||
{
|
||||
if (array[i].desc == EFL_IO_READER_EVENT_CAN_READ_CHANGED)
|
||||
_parent_read_listeners_modify(pd, -1);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
_cb_out(void *data, const Efl_Event *event EINA_UNUSED)
|
||||
{
|
||||
Eo *obj = data;
|
||||
efl_io_reader_can_read_set(obj, EINA_TRUE);
|
||||
}
|
||||
|
||||
static void
|
||||
_cb_in(void *data, const Efl_Event *event EINA_UNUSED)
|
||||
{
|
||||
Eo *obj = data;
|
||||
efl_io_writer_can_write_set(obj, EINA_TRUE);
|
||||
}
|
||||
|
||||
|
||||
EFL_CALLBACKS_ARRAY_DEFINE(_event_callback_watch,
|
||||
{ EFL_EVENT_CALLBACK_ADD, _cb_event_callback_add },
|
||||
{ EFL_EVENT_CALLBACK_DEL, _cb_event_callback_del });
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
EOLIAN static Efl_Loop *
|
||||
_efl_app_loop_main_get(Eo *obj EINA_UNUSED, void *pd EINA_UNUSED)
|
||||
{
|
||||
if (_mainloop_singleton) return _mainloop_singleton;
|
||||
_mainloop_singleton = efl_add(EFL_APP_CLASS, NULL);
|
||||
_mainloop_singleton_data = efl_data_scope_get(_mainloop_singleton, EFL_LOOP_CLASS);
|
||||
return _mainloop_singleton;
|
||||
}
|
||||
|
||||
EOLIAN static const Efl_Version *
|
||||
_efl_app_build_efl_version_get(Eo *obj EINA_UNUSED, Efl_App_Data *pd EINA_UNUSED)
|
||||
{
|
||||
return &_app_efl_version;
|
||||
}
|
||||
|
||||
EOLIAN static const Efl_Version *
|
||||
_efl_app_efl_version_get(Eo *obj EINA_UNUSED, Efl_App_Data *pd EINA_UNUSED)
|
||||
{
|
||||
/* vanilla EFL: flavor = NULL */
|
||||
static const Efl_Version version = {
|
||||
.major = VMAJ,
|
||||
.minor = VMIN,
|
||||
.micro = VMIC,
|
||||
.revision = VREV,
|
||||
.build_id = EFL_BUILD_ID,
|
||||
.flavor = NULL
|
||||
};
|
||||
return &version;
|
||||
}
|
||||
|
||||
EOLIAN static Efl_Object *
|
||||
_efl_app_efl_object_constructor(Eo *obj, Efl_App_Data *pd)
|
||||
{
|
||||
obj = efl_constructor(efl_super(obj, MY_CLASS));
|
||||
efl_event_callback_array_add(obj, _event_callback_watch(), pd);
|
||||
pd->fd.in = 1;
|
||||
pd->fd.out = 0;
|
||||
pd->fd.can_write = EINA_TRUE;
|
||||
pd->fd.in_handler =
|
||||
efl_add(EFL_LOOP_HANDLER_CLASS, obj,
|
||||
efl_loop_handler_fd_set(efl_added, pd->fd.in),
|
||||
efl_event_callback_add
|
||||
(efl_added, EFL_LOOP_HANDLER_EVENT_WRITE, _cb_in, obj));
|
||||
pd->fd.out_handler =
|
||||
efl_add(EFL_LOOP_HANDLER_CLASS, obj,
|
||||
efl_loop_handler_fd_set(efl_added, pd->fd.out),
|
||||
efl_event_callback_add
|
||||
(efl_added, EFL_LOOP_HANDLER_EVENT_READ, _cb_out, obj));
|
||||
return obj;
|
||||
}
|
||||
|
||||
EOLIAN static void
|
||||
_efl_app_efl_object_destructor(Eo *obj, Efl_App_Data *pd)
|
||||
{
|
||||
efl_del(pd->fd.in_handler);
|
||||
efl_del(pd->fd.out_handler);
|
||||
pd->fd.in_handler = NULL;
|
||||
pd->fd.out_handler = NULL;
|
||||
pd->fd.in = -1;
|
||||
pd->fd.out = -1;
|
||||
efl_destructor(efl_super(obj, MY_CLASS));
|
||||
}
|
||||
|
||||
EOLIAN static Eina_Error
|
||||
_efl_app_efl_io_closer_close(Eo *obj, Efl_App_Data *pd)
|
||||
{
|
||||
EINA_SAFETY_ON_TRUE_RETURN_VAL(efl_io_closer_closed_get(obj), EBADF);
|
||||
efl_io_writer_can_write_set(obj, EINA_FALSE);
|
||||
efl_io_reader_can_read_set(obj, EINA_FALSE);
|
||||
efl_io_reader_eos_set(obj, EINA_TRUE);
|
||||
if (pd->fd.in_handler) efl_del(pd->fd.in_handler);
|
||||
if (pd->fd.out_handler) efl_del(pd->fd.out_handler);
|
||||
pd->fd.in = -1;
|
||||
pd->fd.out = -1;
|
||||
pd->fd.in_handler = NULL;
|
||||
pd->fd.out_handler = NULL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
EOLIAN static Eina_Bool
|
||||
_efl_app_efl_io_closer_closed_get(Eo *obj EINA_UNUSED, Efl_App_Data *pd)
|
||||
{
|
||||
if ((pd->fd.in == -1) && (pd->fd.out == -1)) return EINA_TRUE;
|
||||
return EINA_FALSE;
|
||||
}
|
||||
|
||||
EOLIAN static Eina_Error
|
||||
_efl_app_efl_io_reader_read(Eo *obj, Efl_App_Data *pd, Eina_Rw_Slice *rw_slice)
|
||||
{
|
||||
ssize_t r;
|
||||
|
||||
errno = 0;
|
||||
if (pd->fd.out == -1) goto err;
|
||||
|
||||
do
|
||||
{
|
||||
errno = 0;
|
||||
r = read(pd->fd.out, rw_slice->mem, rw_slice->len);
|
||||
if (r == -1)
|
||||
{
|
||||
if (errno == EINTR) continue;
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
while (r == -1);
|
||||
|
||||
rw_slice->len = r;
|
||||
if (r == 0)
|
||||
{
|
||||
efl_io_reader_can_read_set(obj, EINA_FALSE);
|
||||
efl_io_reader_eos_set(obj, EINA_TRUE);
|
||||
close(pd->fd.out);
|
||||
pd->fd.out = -1;
|
||||
efl_del(pd->fd.out_handler);
|
||||
pd->fd.out_handler = NULL;
|
||||
return EPIPE;
|
||||
}
|
||||
return 0;
|
||||
err:
|
||||
if ((pd->fd.out != -1) && (errno != EAGAIN))
|
||||
{
|
||||
close(pd->fd.out);
|
||||
pd->fd.out = -1;
|
||||
efl_del(pd->fd.out_handler);
|
||||
pd->fd.out_handler = NULL;
|
||||
}
|
||||
rw_slice->len = 0;
|
||||
rw_slice->mem = NULL;
|
||||
efl_io_reader_can_read_set(obj, EINA_FALSE);
|
||||
return EINVAL;
|
||||
}
|
||||
|
||||
EOLIAN static void
|
||||
_efl_app_efl_io_reader_can_read_set(Eo *obj, Efl_App_Data *pd, Eina_Bool can_read)
|
||||
{
|
||||
Eina_Bool old = efl_io_reader_can_read_get(obj);
|
||||
if (old == can_read) return;
|
||||
pd->fd.can_read = can_read;
|
||||
if (can_read)
|
||||
efl_loop_handler_active_set(pd->fd.in_handler, 0);
|
||||
else
|
||||
efl_loop_handler_active_set(pd->fd.in_handler,
|
||||
EFL_LOOP_HANDLER_FLAGS_READ);
|
||||
efl_event_callback_call(obj, EFL_IO_READER_EVENT_CAN_READ_CHANGED, NULL);
|
||||
}
|
||||
|
||||
EOLIAN static Eina_Bool
|
||||
_efl_app_efl_io_reader_can_read_get(Eo *obj EINA_UNUSED, Efl_App_Data *pd)
|
||||
{
|
||||
return pd->fd.can_read;
|
||||
}
|
||||
|
||||
EOLIAN static void
|
||||
_efl_app_efl_io_reader_eos_set(Eo *obj, Efl_App_Data *pd, Eina_Bool is_eos)
|
||||
{
|
||||
Eina_Bool old = efl_io_reader_eos_get(obj);
|
||||
if (old == is_eos) return;
|
||||
|
||||
pd->fd.eos_read = is_eos;
|
||||
if (!is_eos) return;
|
||||
if (pd->fd.out_handler)
|
||||
efl_loop_handler_active_set(pd->fd.out_handler, 0);
|
||||
efl_event_callback_call(obj, EFL_IO_READER_EVENT_EOS, NULL);
|
||||
}
|
||||
|
||||
EOLIAN static Eina_Bool
|
||||
_efl_app_efl_io_reader_eos_get(Eo *obj EINA_UNUSED, Efl_App_Data *pd)
|
||||
{
|
||||
return pd->fd.eos_read;
|
||||
}
|
||||
|
||||
EOLIAN static Eina_Error
|
||||
_efl_app_efl_io_writer_write(Eo *obj, Efl_App_Data *pd, Eina_Slice *slice, Eina_Slice *remaining)
|
||||
{
|
||||
ssize_t r;
|
||||
|
||||
errno = 0;
|
||||
if (pd->fd.in == -1) goto err;
|
||||
|
||||
do
|
||||
{
|
||||
errno = 0;
|
||||
r = write(pd->fd.in, slice->mem, slice->len);
|
||||
if (r == -1)
|
||||
{
|
||||
if (errno == EINTR) continue;
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
while (r == -1);
|
||||
|
||||
if (remaining)
|
||||
{
|
||||
remaining->len = slice->len - r;
|
||||
remaining->bytes = slice->bytes + r;
|
||||
}
|
||||
slice->len = r;
|
||||
|
||||
if ((slice) && (slice->len > 0))
|
||||
efl_io_writer_can_write_set(obj, EINA_FALSE);
|
||||
if (r == 0)
|
||||
{
|
||||
close(pd->fd.in);
|
||||
pd->fd.in = -1;
|
||||
efl_del(pd->fd.in_handler);
|
||||
pd->fd.in_handler = NULL;
|
||||
return EPIPE;
|
||||
}
|
||||
return 0;
|
||||
err:
|
||||
if ((pd->fd.in != -1) && (errno != EAGAIN))
|
||||
{
|
||||
close(pd->fd.in);
|
||||
pd->fd.in = -1;
|
||||
efl_del(pd->fd.in_handler);
|
||||
pd->fd.in_handler = NULL;
|
||||
}
|
||||
if (remaining) *remaining = *slice;
|
||||
slice->len = 0;
|
||||
slice->mem = NULL;
|
||||
efl_io_writer_can_write_set(obj, EINA_FALSE);
|
||||
return EINVAL;
|
||||
}
|
||||
|
||||
EOLIAN static void
|
||||
_efl_app_efl_io_writer_can_write_set(Eo *obj, Efl_App_Data *pd, Eina_Bool can_write)
|
||||
{
|
||||
Eina_Bool old = efl_io_writer_can_write_get(obj);
|
||||
if (old == can_write) return;
|
||||
pd->fd.can_write = can_write;
|
||||
if (can_write)
|
||||
efl_loop_handler_active_set(pd->fd.in_handler, 0);
|
||||
else
|
||||
efl_loop_handler_active_set(pd->fd.in_handler,
|
||||
EFL_LOOP_HANDLER_FLAGS_WRITE);
|
||||
efl_event_callback_call(obj, EFL_IO_WRITER_EVENT_CAN_WRITE_CHANGED, NULL);
|
||||
}
|
||||
|
||||
EOLIAN static Eina_Bool
|
||||
_efl_app_efl_io_writer_can_write_get(Eo *obj EINA_UNUSED, Efl_App_Data *pd)
|
||||
{
|
||||
return pd->fd.can_write;
|
||||
}
|
||||
|
||||
#ifdef _WIN32
|
||||
#else
|
||||
static const signed char primap[EFL_TASK_PRIORITY_ULTRA + 1] =
|
||||
{
|
||||
10, // EFL_TASK_PRIORITY_NORMAL
|
||||
19, // EFL_TASK_PRIORITY_BACKGROUND
|
||||
15, // EFL_TASK_PRIORITY_LOW
|
||||
5, // EFL_TASK_PRIORITY_HIGH
|
||||
0 // EFL_TASK_PRIORITY_ULTRA
|
||||
};
|
||||
#endif
|
||||
|
||||
EOLIAN static void
|
||||
_efl_app_efl_task_priority_set(Eo *obj, Efl_App_Data *pd EINA_UNUSED, Efl_Task_Priority priority)
|
||||
{
|
||||
efl_task_priority_set(efl_super(obj, MY_CLASS), priority);
|
||||
#ifdef _WIN32
|
||||
#else
|
||||
// -20 (high) -> 19 (low)
|
||||
int p = 0;
|
||||
|
||||
if ((priority >= EFL_TASK_PRIORITY_NORMAL) &&
|
||||
(priority <= EFL_TASK_PRIORITY_ULTRA))
|
||||
p = primap[priority];
|
||||
setpriority(PRIO_PROCESS, 0, p);
|
||||
#endif
|
||||
}
|
||||
|
||||
EOLIAN static Efl_Task_Priority
|
||||
_efl_app_efl_task_priority_get(Eo *obj, Efl_App_Data *pd EINA_UNUSED)
|
||||
{
|
||||
Efl_Task_Priority pri = EFL_TASK_PRIORITY_NORMAL;
|
||||
#ifdef _WIN32
|
||||
#else
|
||||
int p, i, dist = 0x7fffffff, d;
|
||||
|
||||
errno = 0;
|
||||
p = getpriority(PRIO_PROCESS, 0);
|
||||
if (errno != 0)
|
||||
return efl_task_priority_get(efl_super(obj, MY_CLASS));
|
||||
|
||||
// find the closest matching priority in primap
|
||||
for (i = EFL_TASK_PRIORITY_NORMAL; i <= EFL_TASK_PRIORITY_ULTRA; i++)
|
||||
{
|
||||
d = primap[i] - p;
|
||||
if (d < 0) d = -d;
|
||||
if (d < dist)
|
||||
{
|
||||
pri = i;
|
||||
dist = d;
|
||||
}
|
||||
}
|
||||
|
||||
Efl_Task_Data *td = efl_data_scope_get(obj, EFL_TASK_CLASS);
|
||||
if (td) td->priority = pri;
|
||||
#endif
|
||||
return pri;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "efl_app.eo.c"
|
|
@ -0,0 +1,57 @@
|
|||
import efl_types;
|
||||
import eina_types;
|
||||
|
||||
class Efl.App (Efl.Loop)
|
||||
{
|
||||
[[ ]]
|
||||
methods {
|
||||
@property loop_main @class {
|
||||
[[ Points to the main loop instance of the application. ]]
|
||||
get {}
|
||||
values {
|
||||
main_loop: Efl.Loop; [[Application main loop]]
|
||||
}
|
||||
}
|
||||
@property build_efl_version {
|
||||
[[ Indicates the version of EFL with which this application was
|
||||
compiled against/for.
|
||||
|
||||
This might differ from @.efl_version.
|
||||
]]
|
||||
get {}
|
||||
values {
|
||||
@cref version: Efl.Version; [[Efl version]]
|
||||
}
|
||||
}
|
||||
@property efl_version {
|
||||
[[ Indicates the currently running version of EFL.
|
||||
|
||||
This might differ from @.build_efl_version.
|
||||
]]
|
||||
get {}
|
||||
values {
|
||||
@cref version: Efl.Version; [[Efl version]]
|
||||
}
|
||||
}
|
||||
}
|
||||
events {
|
||||
pause; [[Called when the application is not going be displayed or otherwise used by a user for some time]]
|
||||
resume; [[Called before a window is rendered after a pause event]]
|
||||
terminate; [[Called before starting the shutdown of the application]]
|
||||
signal,usr1; [[System specific, but on unix maps to SIGUSR1 signal to the process - only called on main loop object]]
|
||||
signal,usr2; [[System specific, but on unix maps to SIGUSR2 signal to the process - only called on main loop object]]
|
||||
signal,hup; [[System specific, but on unix maps to SIGHUP signal to the process - only called on main loop object]]
|
||||
}
|
||||
implements {
|
||||
Efl.Object.constructor;
|
||||
Efl.Object.destructor;
|
||||
Efl.Io.Closer.close;
|
||||
Efl.Io.Closer.closed { get; }
|
||||
Efl.Io.Reader.read;
|
||||
Efl.Io.Reader.can_read { get; set; }
|
||||
Efl.Io.Reader.eos { get; set; }
|
||||
Efl.Io.Writer.write;
|
||||
Efl.Io.Writer.can_write { get; set; }
|
||||
Efl.Task.priority { get; set; }
|
||||
}
|
||||
}
|
|
@ -0,0 +1,245 @@
|
|||
#ifdef HAVE_CONFIG_H
|
||||
# include <config.h>
|
||||
#endif
|
||||
|
||||
#define EFL_IO_READER_PROTECTED 1
|
||||
#define EFL_IO_WRITER_PROTECTED 1
|
||||
#define EFL_IO_CLOSER_PROTECTED 1
|
||||
|
||||
#include <Ecore.h>
|
||||
|
||||
#include "ecore_private.h"
|
||||
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <string.h>
|
||||
|
||||
#define MY_CLASS EFL_APPTHREAD_CLASS
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
EOLIAN static Efl_Object *
|
||||
_efl_appthread_efl_object_constructor(Eo *obj, Efl_Appthread_Data *pd)
|
||||
{
|
||||
obj = efl_constructor(efl_super(obj, MY_CLASS));
|
||||
pd->fd.in = -1;
|
||||
pd->fd.out = -1;
|
||||
pd->fd.can_write = EINA_TRUE;
|
||||
pd->ctrl.in = -1;
|
||||
pd->ctrl.out = -1;
|
||||
return obj;
|
||||
}
|
||||
|
||||
EOLIAN static void
|
||||
_efl_appthread_efl_object_destructor(Eo *obj, Efl_Appthread_Data *pd)
|
||||
{
|
||||
if (pd->fd.in >= 0)
|
||||
{
|
||||
efl_del(pd->fd.in_handler);
|
||||
efl_del(pd->fd.out_handler);
|
||||
efl_del(pd->ctrl.in_handler);
|
||||
efl_del(pd->ctrl.out_handler);
|
||||
close(pd->fd.in);
|
||||
close(pd->fd.out);
|
||||
close(pd->ctrl.in);
|
||||
close(pd->ctrl.out);
|
||||
pd->fd.in_handler = NULL;
|
||||
pd->fd.out_handler = NULL;
|
||||
pd->ctrl.in_handler = NULL;
|
||||
pd->ctrl.out_handler = NULL;
|
||||
pd->fd.in = -1;
|
||||
pd->fd.out = -1;
|
||||
pd->ctrl.in = -1;
|
||||
pd->ctrl.out = -1;
|
||||
}
|
||||
efl_destructor(efl_super(obj, MY_CLASS));
|
||||
}
|
||||
|
||||
EOLIAN static Eina_Error
|
||||
_efl_appthread_efl_io_closer_close(Eo *obj, Efl_Appthread_Data *pd)
|
||||
{
|
||||
EINA_SAFETY_ON_TRUE_RETURN_VAL(efl_io_closer_closed_get(obj), EBADF);
|
||||
efl_io_writer_can_write_set(obj, EINA_FALSE);
|
||||
efl_io_reader_can_read_set(obj, EINA_FALSE);
|
||||
efl_io_reader_eos_set(obj, EINA_TRUE);
|
||||
if (pd->fd.in >= 0) close(pd->fd.in);
|
||||
if (pd->fd.out >= 0) close(pd->fd.out);
|
||||
if (pd->fd.in_handler) efl_del(pd->fd.in_handler);
|
||||
if (pd->fd.out_handler) efl_del(pd->fd.out_handler);
|
||||
pd->fd.in = -1;
|
||||
pd->fd.out = -1;
|
||||
pd->fd.in_handler = NULL;
|
||||
pd->fd.out_handler = NULL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
EOLIAN static Eina_Bool
|
||||
_efl_appthread_efl_io_closer_closed_get(Eo *obj EINA_UNUSED, Efl_Appthread_Data *pd)
|
||||
{
|
||||
if ((pd->fd.in == -1) && (pd->fd.out == -1)) return EINA_TRUE;
|
||||
return EINA_FALSE;
|
||||
}
|
||||
|
||||
EOLIAN static Eina_Error
|
||||
_efl_appthread_efl_io_reader_read(Eo *obj, Efl_Appthread_Data *pd, Eina_Rw_Slice *rw_slice)
|
||||
{
|
||||
ssize_t r;
|
||||
|
||||
errno = 0;
|
||||
if (pd->fd.out == -1) goto err;
|
||||
|
||||
do
|
||||
{
|
||||
errno = 0;
|
||||
r = read(pd->fd.out, rw_slice->mem, rw_slice->len);
|
||||
if (r == -1)
|
||||
{
|
||||
if (errno == EINTR) continue;
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
while (r == -1);
|
||||
|
||||
rw_slice->len = r;
|
||||
if (r == 0)
|
||||
{
|
||||
efl_io_reader_can_read_set(obj, EINA_FALSE);
|
||||
efl_io_reader_eos_set(obj, EINA_TRUE);
|
||||
close(pd->fd.out);
|
||||
pd->fd.out = -1;
|
||||
efl_del(pd->fd.out_handler);
|
||||
pd->fd.out_handler = NULL;
|
||||
return EPIPE;
|
||||
}
|
||||
return 0;
|
||||
err:
|
||||
if ((pd->fd.out != -1) && (errno != EAGAIN))
|
||||
{
|
||||
close(pd->fd.out);
|
||||
pd->fd.out = -1;
|
||||
efl_del(pd->fd.out_handler);
|
||||
pd->fd.out_handler = NULL;
|
||||
}
|
||||
rw_slice->len = 0;
|
||||
rw_slice->mem = NULL;
|
||||
efl_io_reader_can_read_set(obj, EINA_FALSE);
|
||||
return EINVAL;
|
||||
}
|
||||
|
||||
EOLIAN static void
|
||||
_efl_appthread_efl_io_reader_can_read_set(Eo *obj, Efl_Appthread_Data *pd, Eina_Bool can_read)
|
||||
{
|
||||
Eina_Bool old = efl_io_reader_can_read_get(obj);
|
||||
if (old == can_read) return;
|
||||
pd->fd.can_read = can_read;
|
||||
if (can_read)
|
||||
efl_loop_handler_active_set(pd->fd.in_handler, 0);
|
||||
else
|
||||
efl_loop_handler_active_set(pd->fd.in_handler,
|
||||
EFL_LOOP_HANDLER_FLAGS_READ);
|
||||
efl_event_callback_call(obj, EFL_IO_READER_EVENT_CAN_READ_CHANGED, NULL);
|
||||
}
|
||||
|
||||
EOLIAN static Eina_Bool
|
||||
_efl_appthread_efl_io_reader_can_read_get(Eo *obj EINA_UNUSED, Efl_Appthread_Data *pd)
|
||||
{
|
||||
return pd->fd.can_read;
|
||||
}
|
||||
|
||||
EOLIAN static void
|
||||
_efl_appthread_efl_io_reader_eos_set(Eo *obj, Efl_Appthread_Data *pd, Eina_Bool is_eos)
|
||||
{
|
||||
Eina_Bool old = efl_io_reader_eos_get(obj);
|
||||
if (old == is_eos) return;
|
||||
|
||||
pd->fd.eos_read = is_eos;
|
||||
if (!is_eos) return;
|
||||
if (pd->fd.out_handler)
|
||||
efl_loop_handler_active_set(pd->fd.out_handler, 0);
|
||||
efl_event_callback_call(obj, EFL_IO_READER_EVENT_EOS, NULL);
|
||||
}
|
||||
|
||||
EOLIAN static Eina_Bool
|
||||
_efl_appthread_efl_io_reader_eos_get(Eo *obj EINA_UNUSED, Efl_Appthread_Data *pd)
|
||||
{
|
||||
return pd->fd.eos_read;
|
||||
}
|
||||
|
||||
EOLIAN static Eina_Error
|
||||
_efl_appthread_efl_io_writer_write(Eo *obj, Efl_Appthread_Data *pd, Eina_Slice *slice, Eina_Slice *remaining)
|
||||
{
|
||||
ssize_t r;
|
||||
|
||||
errno = 0;
|
||||
if (pd->fd.in == -1) goto err;
|
||||
|
||||
do
|
||||
{
|
||||
errno = 0;
|
||||
r = write(pd->fd.in, slice->mem, slice->len);
|
||||
if (r == -1)
|
||||
{
|
||||
if (errno == EINTR) continue;
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
while (r == -1);
|
||||
|
||||
if (remaining)
|
||||
{
|
||||
remaining->len = slice->len - r;
|
||||
remaining->bytes = slice->bytes + r;
|
||||
}
|
||||
slice->len = r;
|
||||
|
||||
if ((slice) && (slice->len > 0))
|
||||
efl_io_writer_can_write_set(obj, EINA_FALSE);
|
||||
if (r == 0)
|
||||
{
|
||||
close(pd->fd.in);
|
||||
pd->fd.in = -1;
|
||||
efl_del(pd->fd.in_handler);
|
||||
pd->fd.in_handler = NULL;
|
||||
return EPIPE;
|
||||
}
|
||||
return 0;
|
||||
err:
|
||||
if ((pd->fd.in != -1) && (errno != EAGAIN))
|
||||
{
|
||||
close(pd->fd.in);
|
||||
pd->fd.in = -1;
|
||||
efl_del(pd->fd.in_handler);
|
||||
pd->fd.in_handler = NULL;
|
||||
}
|
||||
if (remaining) *remaining = *slice;
|
||||
slice->len = 0;
|
||||
slice->mem = NULL;
|
||||
efl_io_writer_can_write_set(obj, EINA_FALSE);
|
||||
return EINVAL;
|
||||
}
|
||||
|
||||
EOLIAN static void
|
||||
_efl_appthread_efl_io_writer_can_write_set(Eo *obj, Efl_Appthread_Data *pd, Eina_Bool can_write)
|
||||
{
|
||||
Eina_Bool old = efl_io_writer_can_write_get(obj);
|
||||
if (old == can_write) return;
|
||||
pd->fd.can_write = can_write;
|
||||
if (can_write)
|
||||
efl_loop_handler_active_set(pd->fd.in_handler, 0);
|
||||
else
|
||||
efl_loop_handler_active_set(pd->fd.in_handler,
|
||||
EFL_LOOP_HANDLER_FLAGS_WRITE);
|
||||
efl_event_callback_call(obj, EFL_IO_WRITER_EVENT_CAN_WRITE_CHANGED, NULL);
|
||||
}
|
||||
|
||||
EOLIAN static Eina_Bool
|
||||
_efl_appthread_efl_io_writer_can_write_get(Eo *obj EINA_UNUSED, Efl_Appthread_Data *pd)
|
||||
{
|
||||
return pd->fd.can_write;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "efl_appthread.eo.c"
|
|
@ -0,0 +1,22 @@
|
|||
import efl_types;
|
||||
import eina_types;
|
||||
|
||||
class Efl.Appthread (Efl.Loop)
|
||||
{
|
||||
[[ ]]
|
||||
methods {
|
||||
}
|
||||
events {
|
||||
}
|
||||
implements {
|
||||
Efl.Object.constructor;
|
||||
Efl.Object.destructor;
|
||||
Efl.Io.Closer.close;
|
||||
Efl.Io.Closer.closed { get; }
|
||||
Efl.Io.Reader.read;
|
||||
Efl.Io.Reader.can_read { get; set; }
|
||||
Efl.Io.Reader.eos { get; set; }
|
||||
Efl.Io.Writer.write;
|
||||
Efl.Io.Writer.can_write { get; set; }
|
||||
}
|
||||
}
|
|
@ -179,15 +179,30 @@ _foreach_env(const Eina_Hash *hash EINA_UNUSED, const void *key, void *data, voi
|
|||
return EINA_TRUE;
|
||||
}
|
||||
|
||||
static Eina_Value
|
||||
_efl_loop_task_exit(void *data, const Eina_Value v,
|
||||
const Eina_Future *dead EINA_UNUSED)
|
||||
{
|
||||
Eo *obj = data;
|
||||
|
||||
efl_event_callback_call(obj, EFL_TASK_EVENT_EXIT, NULL);
|
||||
efl_unref(obj);
|
||||
return v;
|
||||
}
|
||||
|
||||
static void
|
||||
_exe_exit_eval(Eo *obj, Efl_Exe_Data *pd)
|
||||
{
|
||||
// XXX: defer the below in a job
|
||||
if ((pd->fd.out == -1) && (pd->fd.exited_read == -1) &&
|
||||
(!pd->exit_called))
|
||||
if ((pd->fd.out == -1) && /*(pd->fd.in == -1) &&*/
|
||||
(pd->fd.exited_read == -1) && (!pd->exit_called))
|
||||
{
|
||||
Eina_Future *job;
|
||||
Eo *loop = efl_provider_find(obj, EFL_LOOP_CLASS);
|
||||
|
||||
pd->exit_called = EINA_TRUE;
|
||||
efl_event_callback_call(obj, EFL_TASK_EVENT_EXIT, NULL);
|
||||
efl_ref(obj);
|
||||
job = eina_future_then(efl_loop_job(loop), _efl_loop_task_exit, obj);
|
||||
efl_future_Eina_FutureXXX_then(loop, job);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -666,10 +681,11 @@ _efl_exe_efl_io_reader_can_read_set(Eo *obj, Efl_Exe_Data *pd, Eina_Bool can_rea
|
|||
Eina_Bool old = efl_io_reader_can_read_get(obj);
|
||||
if (old == can_read) return;
|
||||
pd->fd.can_read = can_read;
|
||||
if (!pd->fd.out_handler) return;
|
||||
if (can_read)
|
||||
efl_loop_handler_active_set(pd->fd.in_handler, 0);
|
||||
efl_loop_handler_active_set(pd->fd.out_handler, 0);
|
||||
else
|
||||
efl_loop_handler_active_set(pd->fd.in_handler,
|
||||
efl_loop_handler_active_set(pd->fd.out_handler,
|
||||
EFL_LOOP_HANDLER_FLAGS_READ);
|
||||
efl_event_callback_call(obj, EFL_IO_READER_EVENT_CAN_READ_CHANGED, NULL);
|
||||
}
|
||||
|
|
|
@ -107,9 +107,9 @@
|
|||
#define EFL_MAIN_EX() \
|
||||
EFL_CALLBACKS_ARRAY_DEFINE(_efl_main_ex, \
|
||||
{ EFL_LOOP_EVENT_ARGUMENTS, efl_main }, \
|
||||
{ EFL_LOOP_EVENT_PAUSE, efl_pause }, \
|
||||
{ EFL_LOOP_EVENT_RESUME, efl_resume }, \
|
||||
{ EFL_LOOP_EVENT_TERMINATE, efl_terminate }); \
|
||||
{ EFL_APP_EVENT_PAUSE, efl_pause }, \
|
||||
{ EFL_APP_EVENT_RESUME, efl_resume }, \
|
||||
{ EFL_APP_EVENT_TERMINATE, efl_terminate }); \
|
||||
int main(int argc, char **argv) \
|
||||
{ \
|
||||
Eina_Value *ret__; \
|
||||
|
|
|
@ -8,9 +8,6 @@
|
|||
#include <unistd.h>
|
||||
#include <math.h>
|
||||
#include <sys/time.h>
|
||||
#ifndef _WIN32
|
||||
# include <sys/resource.h>
|
||||
#endif
|
||||
#include <errno.h>
|
||||
|
||||
#include "Ecore.h"
|
||||
|
@ -53,8 +50,6 @@ _efl_loop_message_handler_get(Eo *obj EINA_UNUSED, void *pd EINA_UNUSED, Efl_Loo
|
|||
return mh.handler;
|
||||
}
|
||||
|
||||
Efl_Version _app_efl_version = { 0, 0, 0, 0, NULL, NULL };
|
||||
|
||||
Eo *_mainloop_singleton = NULL;
|
||||
Efl_Loop_Data *_mainloop_singleton_data = NULL;
|
||||
|
||||
|
@ -63,19 +58,10 @@ static Eina_List *_environ_strings_set = NULL;
|
|||
|
||||
static void _clean_old_environ(void);
|
||||
|
||||
EOLIAN static Efl_Loop *
|
||||
_efl_loop_main_get(Efl_Class *klass EINA_UNUSED, void *_pd EINA_UNUSED)
|
||||
{
|
||||
if (_mainloop_singleton) return _mainloop_singleton;
|
||||
_mainloop_singleton = efl_add(EFL_LOOP_CLASS, NULL);
|
||||
_mainloop_singleton_data = efl_data_scope_get(_mainloop_singleton, EFL_LOOP_CLASS);
|
||||
return _mainloop_singleton;
|
||||
}
|
||||
|
||||
EAPI Eo *
|
||||
efl_main_loop_get(void)
|
||||
{
|
||||
return efl_loop_main_get(EFL_LOOP_CLASS);
|
||||
return efl_app_loop_main_get(EFL_APP_CLASS);
|
||||
}
|
||||
|
||||
EOLIAN static void
|
||||
|
@ -172,8 +158,8 @@ efl_loop_exit_code_process(Eina_Value *value)
|
|||
Eina_Value v = EINA_VALUE_EMPTY;
|
||||
|
||||
eina_value_setup(&v, EINA_VALUE_TYPE_INT);
|
||||
if (!eina_value_convert(&v, value)) r = -1;
|
||||
else eina_value_get(&v, &v);
|
||||
if (!eina_value_convert(value, &v)) r = -1;
|
||||
else eina_value_get(&v, &r);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -203,7 +189,7 @@ _poll_trigger(void *data, const Efl_Event *event)
|
|||
static void
|
||||
_check_event_catcher_add(void *data, const Efl_Event *event)
|
||||
{
|
||||
const Efl_Callback_Array_Item *array = event->info;
|
||||
const Efl_Callback_Array_Item_Full *array = event->info;
|
||||
Efl_Loop_Data *pd = data;
|
||||
int i;
|
||||
|
||||
|
@ -272,7 +258,7 @@ _check_event_catcher_add(void *data, const Efl_Event *event)
|
|||
static void
|
||||
_check_event_catcher_del(void *data, const Efl_Event *event)
|
||||
{
|
||||
const Efl_Callback_Array_Item *array = event->info;
|
||||
const Efl_Callback_Array_Item_Full *array = event->info;
|
||||
Efl_Loop_Data *pd = data;
|
||||
int i;
|
||||
|
||||
|
@ -337,7 +323,7 @@ _efl_loop_efl_object_constructor(Eo *obj, Efl_Loop_Data *pd)
|
|||
EOLIAN static void
|
||||
_efl_loop_efl_object_destructor(Eo *obj, Efl_Loop_Data *pd)
|
||||
{
|
||||
_ecore_main_content_clear(pd);
|
||||
_ecore_main_content_clear(obj, pd);
|
||||
|
||||
pd->future_message_handler = NULL;
|
||||
|
||||
|
@ -725,6 +711,7 @@ efl_build_version_set(int vmaj, int vmin, int vmic, int revision,
|
|||
_app_efl_version.build_id = build_id ? strdup(build_id) : NULL;
|
||||
}
|
||||
|
||||
/* HHH:
|
||||
EOLIAN static const Efl_Version *
|
||||
_efl_loop_app_efl_version_get(Eo *obj EINA_UNUSED, Efl_Loop_Data *pd EINA_UNUSED)
|
||||
{
|
||||
|
@ -734,7 +721,7 @@ _efl_loop_app_efl_version_get(Eo *obj EINA_UNUSED, Efl_Loop_Data *pd EINA_UNUSED
|
|||
EOLIAN static const Efl_Version *
|
||||
_efl_loop_efl_version_get(Eo *obj EINA_UNUSED, Efl_Loop_Data *pd EINA_UNUSED)
|
||||
{
|
||||
/* vanilla EFL: flavor = NULL */
|
||||
// vanilla EFL: flavor = NULL
|
||||
static const Efl_Version version = {
|
||||
.major = VMAJ,
|
||||
.minor = VMIN,
|
||||
|
@ -745,6 +732,7 @@ _efl_loop_efl_version_get(Eo *obj EINA_UNUSED, Efl_Loop_Data *pd EINA_UNUSED)
|
|||
};
|
||||
return &version;
|
||||
}
|
||||
*/
|
||||
|
||||
static void
|
||||
_env_sync(Efl_Loop_Data *pd, Efl_Task_Data *td)
|
||||
|
@ -903,63 +891,23 @@ _efl_loop_efl_task_env_get(Eo *obj, Efl_Loop_Data *pd, const char *var)
|
|||
eina_lock_release(&_environ_lock);
|
||||
return efl_task_env_get(efl_super(obj, EFL_LOOP_CLASS), var);
|
||||
}
|
||||
#ifdef _WIN32
|
||||
#else
|
||||
static const signed char primap[EFL_TASK_PRIORITY_ULTRA + 1] =
|
||||
{
|
||||
10, // EFL_TASK_PRIORITY_NORMAL
|
||||
19, // EFL_TASK_PRIORITY_BACKGROUND
|
||||
15, // EFL_TASK_PRIORITY_LOW
|
||||
5, // EFL_TASK_PRIORITY_HIGH
|
||||
0 // EFL_TASK_PRIORITY_ULTRA
|
||||
};
|
||||
#endif
|
||||
|
||||
EOLIAN static void
|
||||
_efl_loop_efl_task_priority_set(Eo *obj, Efl_Loop_Data *pd EINA_UNUSED, Efl_Task_Priority priority)
|
||||
EOLIAN static Eina_Bool
|
||||
_efl_loop_efl_task_run(Eo *obj, Efl_Loop_Data *pd EINA_UNUSED)
|
||||
{
|
||||
efl_task_priority_set(efl_super(obj, EFL_LOOP_CLASS), priority);
|
||||
#ifdef _WIN32
|
||||
#else
|
||||
// -20 (high) -> 19 (low)
|
||||
int p = 0;
|
||||
Eina_Value *ret;
|
||||
int real;
|
||||
|
||||
if ((priority >= EFL_TASK_PRIORITY_NORMAL) &&
|
||||
(priority <= EFL_TASK_PRIORITY_ULTRA))
|
||||
p = primap[priority];
|
||||
setpriority(PRIO_PROCESS, 0, p);
|
||||
#endif
|
||||
ret = efl_loop_begin(obj);
|
||||
real = efl_loop_exit_code_process(ret);
|
||||
if (real == 0) return EINA_TRUE;
|
||||
return EINA_FALSE;
|
||||
}
|
||||
|
||||
EOLIAN static Efl_Task_Priority
|
||||
_efl_loop_efl_task_priority_get(Eo *obj EINA_UNUSED, Efl_Loop_Data *pd EINA_UNUSED)
|
||||
EOLIAN static void
|
||||
_efl_loop_efl_task_end(Eo *obj, Efl_Loop_Data *pd EINA_UNUSED)
|
||||
{
|
||||
Efl_Task_Priority pri = EFL_TASK_PRIORITY_NORMAL;
|
||||
#ifdef _WIN32
|
||||
#else
|
||||
int p, i, dist = 0x7fffffff, d;
|
||||
|
||||
errno = 0;
|
||||
p = getpriority(PRIO_PROCESS, 0);
|
||||
if (errno != 0)
|
||||
return efl_task_priority_get(efl_super(obj, EFL_LOOP_CLASS));
|
||||
|
||||
// find the closest matching priority in primap
|
||||
for (i = EFL_TASK_PRIORITY_NORMAL; i <= EFL_TASK_PRIORITY_ULTRA; i++)
|
||||
{
|
||||
d = primap[i] - p;
|
||||
if (d < 0) d = -d;
|
||||
if (d < dist)
|
||||
{
|
||||
pri = i;
|
||||
dist = d;
|
||||
}
|
||||
}
|
||||
|
||||
Efl_Task_Data *td = efl_data_scope_get(obj, EFL_TASK_CLASS);
|
||||
if (td) td->priority = pri;
|
||||
#endif
|
||||
return pri;
|
||||
efl_loop_quit(obj, eina_value_int_init(0));
|
||||
}
|
||||
|
||||
EAPI Eina_Future_Scheduler *
|
||||
|
|
|
@ -20,33 +20,6 @@ class Efl.Loop (Efl.Task)
|
|||
you can provide these if you need to.
|
||||
]]
|
||||
methods {
|
||||
@property main @class {
|
||||
[[Points to the main loop instance of the application.]]
|
||||
get {}
|
||||
values {
|
||||
main_loop: Efl.Loop; [[Application main loop]]
|
||||
}
|
||||
}
|
||||
@property app_efl_version {
|
||||
[[Indicates the version of EFL with which this application was compiled.
|
||||
|
||||
This might differ from @.efl_version.
|
||||
]]
|
||||
get {}
|
||||
values {
|
||||
@cref version: Efl.Version; [[Efl version]]
|
||||
}
|
||||
}
|
||||
@property efl_version {
|
||||
[[Indicates the currently running version of EFL.
|
||||
|
||||
This might differ from @.app_efl_version.
|
||||
]]
|
||||
get {}
|
||||
values {
|
||||
@cref version: Efl.Version; [[Efl version]]
|
||||
}
|
||||
}
|
||||
iterate {
|
||||
[[Runs a single iteration of the main loop to process everything on the
|
||||
queue.]]
|
||||
|
@ -148,18 +121,13 @@ class Efl.Loop (Efl.Task)
|
|||
poll,high; [[Event occurs multiple times per second. The exact tick is undefined and can be adjusted system wide.]]
|
||||
poll,medium; [[Event occurs multiple times per minute. The exact tick is undefined and can be adjusted system wide.]]
|
||||
poll,low; [[Event occurs multiple times every 15 minutes. The exact tick is undefined and can be adjusted system wide.]]
|
||||
pause; [[Called when the window is not going be displayed for some time]]
|
||||
resume; [[Called before a window is rendered after a pause event]]
|
||||
terminate; [[Called before starting the shutdown of Elementary]]
|
||||
signal,usr1; [[System specific, but on unix maps to SIGUSR1 signal to the process - only called on main loop object]]
|
||||
signal,usr2; [[System specific, but on unix maps to SIGUSR2 signal to the process - only called on main loop object]]
|
||||
signal,hup; [[System specific, but on unix maps to SIGHUP signal to the process - only called on main loop object]]
|
||||
}
|
||||
implements {
|
||||
Efl.Object.constructor;
|
||||
Efl.Object.destructor;
|
||||
Efl.Object.provider_find;
|
||||
Efl.Task.env { set; get; }
|
||||
Efl.Task.priority { get; set; }
|
||||
Efl.Task.run;
|
||||
Efl.Task.end;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -111,7 +111,7 @@ _efl_loop_fd_fd_file_get(Eo *obj EINA_UNUSED, Efl_Loop_Fd_Data *pd)
|
|||
static void
|
||||
_check_fd_event_catcher_add(void *data, const Efl_Event *event)
|
||||
{
|
||||
const Efl_Callback_Array_Item *array = event->info;
|
||||
const Efl_Callback_Array_Item_Full *array = event->info;
|
||||
Efl_Loop_Fd_Data *fd = data;
|
||||
Eina_Bool need_reset = EINA_FALSE;
|
||||
int i;
|
||||
|
@ -142,7 +142,7 @@ _check_fd_event_catcher_add(void *data, const Efl_Event *event)
|
|||
static void
|
||||
_check_fd_event_catcher_del(void *data, const Efl_Event *event)
|
||||
{
|
||||
const Efl_Callback_Array_Item *array = event->info;
|
||||
const Efl_Callback_Array_Item_Full *array = event->info;
|
||||
Efl_Loop_Fd_Data *fd = data;
|
||||
Eina_Bool need_reset = EINA_FALSE;
|
||||
int i;
|
||||
|
|
|
@ -132,7 +132,7 @@ _handler_reset(Eo *obj, Efl_Loop_Handler_Data *pd)
|
|||
static Eina_Bool
|
||||
_event_references_update(Efl_Loop_Handler_Data *pd, const Efl_Event *event, int increment)
|
||||
{
|
||||
const Efl_Callback_Array_Item *array = event->info;
|
||||
const Efl_Callback_Array_Item_Full *array = event->info;
|
||||
int i;
|
||||
Eina_Bool need_reset = EINA_FALSE;
|
||||
|
||||
|
|
|
@ -186,8 +186,8 @@ _escape(const char *s)
|
|||
{
|
||||
*d = '\"';
|
||||
d++;
|
||||
*d = 0;
|
||||
}
|
||||
*d = 0;
|
||||
return s2;
|
||||
}
|
||||
|
||||
|
@ -215,7 +215,7 @@ _rebuild_command(Efl_Task_Data *pd)
|
|||
char *str = _escape(arg);
|
||||
if (str)
|
||||
{
|
||||
if (!have_args) eina_strbuf_append(sb, " ");
|
||||
if (have_args) eina_strbuf_append(sb, " ");
|
||||
eina_strbuf_append(sb, str);
|
||||
free(str);
|
||||
have_args = EINA_TRUE;
|
||||
|
@ -272,14 +272,17 @@ _efl_task_arg_value_set(Eo *obj EINA_UNUSED, Efl_Task_Data *pd, unsigned int num
|
|||
|
||||
if (!pd->args) pd->args = eina_array_new(16);
|
||||
count = eina_array_count(pd->args);
|
||||
if (count > num)
|
||||
if ((count > 0) && (count > num))
|
||||
parg = eina_array_data_get(pd->args, num);
|
||||
else
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
for (i = count; i <= num; i++)
|
||||
eina_array_push(pd->args, NULL);
|
||||
{
|
||||
eina_array_push(pd->args, "");
|
||||
eina_array_data_set(pd->args, i, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
if (arg)
|
||||
|
|
|
@ -0,0 +1,917 @@
|
|||
#ifdef HAVE_CONFIG_H
|
||||
# include <config.h>
|
||||
#endif
|
||||
|
||||
#define EFL_IO_READER_PROTECTED 1
|
||||
#define EFL_IO_WRITER_PROTECTED 1
|
||||
#define EFL_IO_CLOSER_PROTECTED 1
|
||||
|
||||
#include <Ecore.h>
|
||||
|
||||
#include "ecore_private.h"
|
||||
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <string.h>
|
||||
|
||||
#define MY_CLASS EFL_THREAD_CLASS
|
||||
|
||||
typedef struct
|
||||
{
|
||||
const char *name;
|
||||
struct {
|
||||
int in, out;
|
||||
Eo *in_handler, *out_handler;
|
||||
} fd, ctrl;
|
||||
struct {
|
||||
unsigned int argc;
|
||||
const char **argv;
|
||||
} args;
|
||||
Efl_Callback_Array_Item_Full *event_cb;
|
||||
} Thread_Data;
|
||||
|
||||
#define CMD_EXIT 1
|
||||
#define CMD_EXITED 2
|
||||
|
||||
typedef struct
|
||||
{
|
||||
int command;
|
||||
int data;
|
||||
} Control_Data;
|
||||
|
||||
typedef struct _Efl_Thread_Data Efl_Thread_Data;
|
||||
|
||||
struct _Efl_Thread_Data
|
||||
{
|
||||
struct {
|
||||
int in, out;
|
||||
Eo *in_handler, *out_handler;
|
||||
Eina_Bool can_read : 1;
|
||||
Eina_Bool eos_read : 1;
|
||||
Eina_Bool can_write : 1;
|
||||
} fd, ctrl;
|
||||
int read_listeners;
|
||||
Eo *loop;
|
||||
Thread_Data *thdat;
|
||||
Efl_Callback_Array_Item_Full *event_cb;
|
||||
Eina_Thread thread;
|
||||
Eina_Bool end_sent : 1;
|
||||
Eina_Bool exit_read : 1;
|
||||
Eina_Bool exit_called : 1;
|
||||
};
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static void
|
||||
_cb_thread_out(void *data, const Efl_Event *event EINA_UNUSED)
|
||||
{
|
||||
Eo *obj = data;
|
||||
efl_io_reader_can_read_set(obj, EINA_TRUE);
|
||||
}
|
||||
|
||||
static void
|
||||
_cb_thread_in(void *data, const Efl_Event *event EINA_UNUSED)
|
||||
{
|
||||
Eo *obj = data;
|
||||
efl_io_writer_can_write_set(obj, EINA_TRUE);
|
||||
}
|
||||
|
||||
static void
|
||||
_cb_thread_ctrl_out(void *data, const Efl_Event *event EINA_UNUSED)
|
||||
{
|
||||
Eo *obj = data;
|
||||
Control_Data cmd;
|
||||
ssize_t ret;
|
||||
Efl_Appthread_Data *ad;
|
||||
|
||||
ad = efl_data_scope_get(obj, EFL_APPTHREAD_CLASS);
|
||||
cmd.command = 0;
|
||||
cmd.data = 0;
|
||||
ret = read(ad->ctrl.out, &cmd, sizeof(Control_Data));
|
||||
if (ret == sizeof(Control_Data))
|
||||
{
|
||||
if (cmd.command == CMD_EXIT)
|
||||
{
|
||||
efl_event_callback_call(obj, EFL_TASK_EVENT_EXIT, NULL);
|
||||
efl_loop_quit(obj, eina_value_int_init(0));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static Eina_Value
|
||||
_efl_loop_arguments_send(void *data, const Eina_Value v,
|
||||
const Eina_Future *dead EINA_UNUSED)
|
||||
|
||||
{
|
||||
Efl_Loop_Arguments arge;
|
||||
Eo *obj = data;
|
||||
Eina_Array *arga;
|
||||
Eina_Stringshare *s;
|
||||
unsigned int argc = efl_task_arg_count_get(obj);
|
||||
unsigned int i;
|
||||
|
||||
arga = eina_array_new(argc);
|
||||
if (v.type == EINA_VALUE_TYPE_ERROR) goto on_error;
|
||||
|
||||
for (i = 0; i < argc; i++)
|
||||
{
|
||||
const char *argv = efl_task_arg_value_get(obj, i);
|
||||
if (argv)
|
||||
eina_array_push(arga, eina_stringshare_add(argv));
|
||||
}
|
||||
arge.argv = arga;
|
||||
arge.initialization = EINA_TRUE;
|
||||
efl_event_callback_call(obj,
|
||||
EFL_LOOP_EVENT_ARGUMENTS, &arge);
|
||||
on_error:
|
||||
while ((s = eina_array_pop(arga))) eina_stringshare_del(s);
|
||||
eina_array_free(arga);
|
||||
return v;
|
||||
}
|
||||
|
||||
static void
|
||||
_appthread_parent_read_listeners_modify(Efl_Appthread_Data *ad, int mod)
|
||||
{
|
||||
ad->read_listeners += mod;
|
||||
|
||||
if (ad->fd.out_handler)
|
||||
{
|
||||
if ((ad->read_listeners == 0) && (mod < 0))
|
||||
efl_loop_handler_active_set
|
||||
(ad->fd.out_handler, EFL_LOOP_HANDLER_FLAGS_NONE);
|
||||
else if ((ad->read_listeners == 1) && (mod > 0))
|
||||
efl_loop_handler_active_set
|
||||
(ad->fd.out_handler, EFL_LOOP_HANDLER_FLAGS_READ);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
_cb_appthread_event_callback_add(void *data, const Efl_Event *event)
|
||||
{
|
||||
Efl_Appthread_Data *ad = data;
|
||||
const Efl_Callback_Array_Item_Full *array = event->info;
|
||||
int i;
|
||||
|
||||
for (i = 0; array[i].desc != NULL; i++)
|
||||
{
|
||||
if (array[i].desc == EFL_IO_READER_EVENT_CAN_READ_CHANGED)
|
||||
_appthread_parent_read_listeners_modify(ad, 1);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
_cb_appthread_event_callback_del(void *data, const Efl_Event *event)
|
||||
{
|
||||
Efl_Appthread_Data *ad = data;
|
||||
const Efl_Callback_Array_Item_Full *array = event->info;
|
||||
int i;
|
||||
|
||||
for (i = 0; array[i].desc != NULL; i++)
|
||||
{
|
||||
if (array[i].desc == EFL_IO_READER_EVENT_CAN_READ_CHANGED)
|
||||
_appthread_parent_read_listeners_modify(ad, -1);
|
||||
}
|
||||
}
|
||||
|
||||
EFL_CALLBACKS_ARRAY_DEFINE(_appthread_event_callback_watch,
|
||||
{ EFL_EVENT_CALLBACK_ADD, _cb_appthread_event_callback_add },
|
||||
{ EFL_EVENT_CALLBACK_DEL, _cb_appthread_event_callback_del });
|
||||
|
||||
static void *
|
||||
_efl_thread_main(void *data, Eina_Thread t)
|
||||
{
|
||||
Efl_Appthread_Data *ad;
|
||||
Thread_Data *thdat = data;
|
||||
Eo *obj;
|
||||
Eina_Value *ret;
|
||||
Control_Data cmd;
|
||||
unsigned int i;
|
||||
int real;
|
||||
Efl_Callback_Array_Item_Full *it;
|
||||
Eina_Future *job;
|
||||
|
||||
if (thdat->name) eina_thread_name_set(t, thdat->name);
|
||||
else eina_thread_name_set(t, "Eflthread");
|
||||
|
||||
obj = efl_add(EFL_APPTHREAD_CLASS, NULL);
|
||||
ad = efl_data_scope_get(obj, EFL_APPTHREAD_CLASS);
|
||||
efl_event_callback_array_add(obj, _appthread_event_callback_watch(), ad);
|
||||
|
||||
// add handlers for "stdio"
|
||||
thdat->fd.in_handler =
|
||||
efl_add(EFL_LOOP_HANDLER_CLASS, obj,
|
||||
efl_loop_handler_fd_set(efl_added, thdat->fd.in),
|
||||
efl_event_callback_add
|
||||
(efl_added, EFL_LOOP_HANDLER_EVENT_WRITE, _cb_thread_in, obj));
|
||||
thdat->fd.out_handler =
|
||||
efl_add(EFL_LOOP_HANDLER_CLASS, obj,
|
||||
efl_loop_handler_fd_set(efl_added, thdat->fd.out),
|
||||
efl_event_callback_add
|
||||
(efl_added, EFL_LOOP_HANDLER_EVENT_READ, _cb_thread_out, obj));
|
||||
// add handlers for control pipes
|
||||
thdat->ctrl.in_handler =
|
||||
efl_add(EFL_LOOP_HANDLER_CLASS, obj,
|
||||
efl_loop_handler_fd_set(efl_added, thdat->ctrl.in));
|
||||
thdat->ctrl.out_handler =
|
||||
efl_add(EFL_LOOP_HANDLER_CLASS, obj,
|
||||
efl_loop_handler_fd_set(efl_added, thdat->ctrl.out),
|
||||
efl_event_callback_add
|
||||
(efl_added, EFL_LOOP_HANDLER_EVENT_READ, _cb_thread_ctrl_out, obj),
|
||||
efl_loop_handler_active_set
|
||||
(efl_added, EFL_LOOP_HANDLER_FLAGS_READ));
|
||||
ad->fd.in = thdat->fd.in;
|
||||
ad->fd.out = thdat->fd.out;
|
||||
ad->ctrl.in = thdat->ctrl.in;
|
||||
ad->ctrl.out = thdat->ctrl.out;
|
||||
ad->fd.in_handler = thdat->fd.in_handler;
|
||||
ad->fd.out_handler = thdat->fd.out_handler;
|
||||
ad->ctrl.in_handler = thdat->ctrl.in_handler;
|
||||
ad->ctrl.out_handler = thdat->ctrl.out_handler;
|
||||
|
||||
if (thdat->event_cb)
|
||||
{
|
||||
for (it = thdat->event_cb; it->func; it++)
|
||||
efl_event_callback_priority_add(obj, it->desc, it->priority,
|
||||
it->func, it->user_data);
|
||||
}
|
||||
for (i = 0; i < thdat->args.argc; i++)
|
||||
efl_task_arg_append(obj, thdat->args.argv[i]);
|
||||
job = eina_future_then(efl_loop_job(obj), _efl_loop_arguments_send, obj);
|
||||
efl_future_Eina_FutureXXX_then(obj, job);
|
||||
|
||||
for (i = 0; i < thdat->args.argc; i++)
|
||||
eina_stringshare_del(thdat->args.argv[i]);
|
||||
free(thdat->args.argv);
|
||||
free(thdat->event_cb);
|
||||
thdat->args.argv = NULL;
|
||||
thdat->event_cb = NULL;
|
||||
|
||||
ret = efl_loop_begin(obj);
|
||||
real = efl_loop_exit_code_process(ret);
|
||||
|
||||
cmd.command = CMD_EXITED;
|
||||
cmd.data = real;
|
||||
write(thdat->ctrl.in, &cmd, sizeof(Control_Data));
|
||||
|
||||
efl_del(obj);
|
||||
|
||||
thdat->fd.in_handler = NULL;
|
||||
thdat->fd.out_handler = NULL;
|
||||
thdat->ctrl.in_handler = NULL;
|
||||
thdat->ctrl.out_handler = NULL;
|
||||
thdat->fd.in = -1;
|
||||
thdat->fd.out = -1;
|
||||
thdat->ctrl.in = -1;
|
||||
thdat->ctrl.out = -1;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static Eina_Value
|
||||
_efl_loop_task_exit(void *data, const Eina_Value v,
|
||||
const Eina_Future *dead EINA_UNUSED)
|
||||
|
||||
{
|
||||
Eo *obj = data;
|
||||
|
||||
efl_event_callback_call(obj, EFL_TASK_EVENT_EXIT, NULL);
|
||||
efl_unref(obj);
|
||||
return v;
|
||||
}
|
||||
|
||||
static void
|
||||
_thread_exit_eval(Eo *obj, Efl_Thread_Data *pd)
|
||||
{
|
||||
if ((pd->fd.out == -1) && /*(pd->fd.in == -1) &&*/
|
||||
(pd->exit_read) && (!pd->exit_called))
|
||||
{
|
||||
Eina_Future *job;
|
||||
Eo *loop = efl_provider_find(obj, EFL_LOOP_CLASS);
|
||||
|
||||
pd->exit_called = EINA_TRUE;
|
||||
efl_ref(obj);
|
||||
job = eina_future_then(efl_loop_job(loop), _efl_loop_task_exit, obj);
|
||||
efl_future_Eina_FutureXXX_then(loop, job);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
_cb_thread_parent_out(void *data, const Efl_Event *event EINA_UNUSED)
|
||||
{
|
||||
Eo *obj = data;
|
||||
efl_io_reader_can_read_set(obj, EINA_TRUE);
|
||||
}
|
||||
|
||||
static void
|
||||
_cb_thread_parent_in(void *data, const Efl_Event *event EINA_UNUSED)
|
||||
{
|
||||
Eo *obj = data;
|
||||
efl_io_writer_can_write_set(obj, EINA_TRUE);
|
||||
}
|
||||
|
||||
static void
|
||||
_cb_thread_parent_ctrl_out(void *data, const Efl_Event *event EINA_UNUSED)
|
||||
{
|
||||
Eo *obj = data;
|
||||
Control_Data cmd;
|
||||
ssize_t ret;
|
||||
Efl_Thread_Data *pd = efl_data_scope_get(obj, MY_CLASS);
|
||||
|
||||
if (!pd) return;
|
||||
|
||||
cmd.command = 0;
|
||||
cmd.data = 0;
|
||||
ret = read(pd->ctrl.out, &cmd, sizeof(Control_Data));
|
||||
if (ret == sizeof(Control_Data))
|
||||
{
|
||||
if (cmd.command == CMD_EXITED)
|
||||
{
|
||||
if (!pd->exit_read)
|
||||
{
|
||||
Efl_Task_Data *td = efl_data_scope_get(obj, EFL_TASK_CLASS);
|
||||
|
||||
if (td) td->exit_code = cmd.data;
|
||||
pd->exit_read = EINA_TRUE;
|
||||
_thread_exit_eval(obj, pd);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static void
|
||||
_thread_parent_read_listeners_modify(Efl_Thread_Data *pd, int mod)
|
||||
{
|
||||
pd->read_listeners += mod;
|
||||
|
||||
if (pd->fd.out_handler)
|
||||
{
|
||||
if ((pd->read_listeners == 0) && (mod < 0))
|
||||
efl_loop_handler_active_set
|
||||
(pd->fd.out_handler, EFL_LOOP_HANDLER_FLAGS_NONE);
|
||||
else if ((pd->read_listeners == 1) && (mod > 0))
|
||||
efl_loop_handler_active_set
|
||||
(pd->fd.out_handler, EFL_LOOP_HANDLER_FLAGS_READ);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
_cb_event_callback_add(void *data, const Efl_Event *event)
|
||||
{
|
||||
Efl_Thread_Data *pd = data;
|
||||
const Efl_Callback_Array_Item_Full *array = event->info;
|
||||
int i;
|
||||
|
||||
for (i = 0; array[i].desc != NULL; i++)
|
||||
{
|
||||
if (array[i].desc == EFL_LOOP_EVENT_ARGUMENTS)
|
||||
{
|
||||
Efl_Callback_Array_Item_Full *event_cb, *it;
|
||||
int num;
|
||||
|
||||
num = 0;
|
||||
if (pd->event_cb)
|
||||
{
|
||||
for (it = pd->event_cb; it->func; it++) num++;
|
||||
}
|
||||
num++;
|
||||
event_cb = realloc(pd->event_cb, (num + 1) * sizeof(Efl_Callback_Array_Item_Full));
|
||||
if (event_cb)
|
||||
{
|
||||
pd->event_cb = event_cb;
|
||||
event_cb[num - 1] = array[i];
|
||||
event_cb[num].desc = NULL;
|
||||
event_cb[num].priority = 0;
|
||||
event_cb[num].func = NULL;
|
||||
event_cb[num].user_data = NULL;
|
||||
}
|
||||
}
|
||||
else if (array[i].desc == EFL_IO_READER_EVENT_CAN_READ_CHANGED)
|
||||
_thread_parent_read_listeners_modify(pd, 1);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
_cb_event_callback_del(void *data, const Efl_Event *event)
|
||||
{
|
||||
Efl_Thread_Data *pd = data;
|
||||
const Efl_Callback_Array_Item_Full *array = event->info;
|
||||
int i;
|
||||
|
||||
for (i = 0; array[i].desc != NULL; i++)
|
||||
{
|
||||
if (array[i].desc == EFL_LOOP_EVENT_ARGUMENTS)
|
||||
{
|
||||
Efl_Callback_Array_Item_Full *it;
|
||||
|
||||
if (pd->event_cb)
|
||||
{
|
||||
Eina_Bool shuffle_down = EINA_FALSE;
|
||||
|
||||
for (it = pd->event_cb; it->func; it++)
|
||||
{
|
||||
if ((it->desc == array[i].desc) &&
|
||||
(it->priority == array[i].priority) &&
|
||||
(it->func == array[i].func) &&
|
||||
(it->user_data == array[i].user_data))
|
||||
shuffle_down = EINA_TRUE;
|
||||
if (shuffle_down) it[0] = it[1];
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (array[i].desc == EFL_IO_READER_EVENT_CAN_READ_CHANGED)
|
||||
_thread_parent_read_listeners_modify(pd, -1);
|
||||
}
|
||||
}
|
||||
|
||||
EFL_CALLBACKS_ARRAY_DEFINE(_event_callback_watch,
|
||||
{ EFL_EVENT_CALLBACK_ADD, _cb_event_callback_add },
|
||||
{ EFL_EVENT_CALLBACK_DEL, _cb_event_callback_del });
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
EOLIAN static Efl_Object *
|
||||
_efl_thread_efl_object_constructor(Eo *obj, Efl_Thread_Data *pd)
|
||||
{
|
||||
obj = efl_constructor(efl_super(obj, MY_CLASS));
|
||||
efl_event_callback_array_add(obj, _event_callback_watch(), pd);
|
||||
pd->fd.in = -1;
|
||||
pd->fd.out = -1;
|
||||
pd->fd.can_write = EINA_TRUE;
|
||||
pd->ctrl.in = -1;
|
||||
pd->ctrl.out = -1;
|
||||
return obj;
|
||||
}
|
||||
|
||||
EOLIAN static void
|
||||
_efl_thread_efl_object_destructor(Eo *obj, Efl_Thread_Data *pd)
|
||||
{
|
||||
if (pd->thdat)
|
||||
{
|
||||
/* we probably shouldn't do this... this simply has to orphan threads if they
|
||||
* lose their parent. this stops shutdown from blocking.
|
||||
// if exit response not read yet, read until fetched
|
||||
if (!pd->exit_read)
|
||||
{
|
||||
Control_Data cmd;
|
||||
ssize_t ret;
|
||||
|
||||
// if it hasn't been asked to exit... ask it
|
||||
if (!pd->end_sent) efl_task_end(obj);
|
||||
cmd.command = 0;
|
||||
cmd.data = 0;
|
||||
ret = read(pd->ctrl.out, &cmd, sizeof(Control_Data));
|
||||
while (ret == sizeof(Control_Data))
|
||||
{
|
||||
if (cmd.command == CMD_EXITED)
|
||||
{
|
||||
if (!pd->exit_read)
|
||||
{
|
||||
Efl_Task_Data *td = efl_data_scope_get(obj, EFL_TASK_CLASS);
|
||||
|
||||
if (td) td->exit_code = cmd.data;
|
||||
pd->exit_read = EINA_TRUE;
|
||||
efl_event_callback_call(obj, EFL_TASK_EVENT_EXIT, NULL);
|
||||
break;
|
||||
}
|
||||
}
|
||||
ret = read(pd->ctrl.out, &cmd, sizeof(Control_Data));
|
||||
}
|
||||
}
|
||||
*/
|
||||
// stop and wait for thread to exit/join here
|
||||
eina_thread_join(pd->thread);
|
||||
efl_del(pd->fd.in_handler);
|
||||
efl_del(pd->fd.out_handler);
|
||||
efl_del(pd->ctrl.in_handler);
|
||||
efl_del(pd->ctrl.out_handler);
|
||||
close(pd->fd.in);
|
||||
close(pd->fd.out);
|
||||
close(pd->ctrl.in);
|
||||
close(pd->ctrl.out);
|
||||
pd->fd.in_handler = NULL;
|
||||
pd->fd.out_handler = NULL;
|
||||
pd->ctrl.in_handler = NULL;
|
||||
pd->ctrl.out_handler = NULL;
|
||||
pd->fd.in = -1;
|
||||
pd->fd.out = -1;
|
||||
pd->ctrl.in = -1;
|
||||
pd->ctrl.out = -1;
|
||||
free(pd->thdat);
|
||||
}
|
||||
free(pd->event_cb);
|
||||
pd->event_cb = NULL;
|
||||
efl_destructor(efl_super(obj, MY_CLASS));
|
||||
}
|
||||
|
||||
EOLIAN static void
|
||||
_efl_thread_efl_object_parent_set(Eo *obj, Efl_Thread_Data *pd, Efl_Object *parent)
|
||||
{
|
||||
efl_parent_set(efl_super(obj, MY_CLASS), parent);
|
||||
pd->loop = efl_provider_find(parent, EFL_LOOP_CLASS);
|
||||
}
|
||||
|
||||
EOLIAN static Eina_Bool
|
||||
_efl_thread_efl_task_run(Eo *obj, Efl_Thread_Data *pd)
|
||||
{
|
||||
Eina_Thread_Priority pri;
|
||||
Thread_Data *thdat;
|
||||
const char *name;
|
||||
int pipe_to_thread[2];
|
||||
int pipe_from_thread[2];
|
||||
unsigned int argc, i, num;
|
||||
Efl_Callback_Array_Item_Full *it;
|
||||
|
||||
thdat = calloc(1, sizeof(Thread_Data));
|
||||
if (!thdat) return EINA_FALSE;
|
||||
thdat->fd.in = -1;
|
||||
thdat->fd.out = -1;
|
||||
thdat->ctrl.in = -1;
|
||||
thdat->ctrl.out = -1;
|
||||
|
||||
if (pipe(pipe_to_thread) != 0)
|
||||
{
|
||||
ERR("Can't create to_thread pipe");
|
||||
free(thdat);
|
||||
return EINA_FALSE;
|
||||
}
|
||||
if (pipe(pipe_from_thread) != 0)
|
||||
{
|
||||
ERR("Can't create from_thread pipe");
|
||||
close(pipe_to_thread[0]);
|
||||
close(pipe_to_thread[1]);
|
||||
free(thdat);
|
||||
return EINA_FALSE;
|
||||
}
|
||||
thdat->fd.in = pipe_from_thread[1]; // write - input to parent
|
||||
thdat->fd.out = pipe_to_thread [0]; // read - output from parent
|
||||
pd->fd.in = pipe_to_thread [1]; // write - input to child
|
||||
pd->fd.out = pipe_from_thread[0]; // read - output from child
|
||||
eina_file_close_on_exec(pd->fd.in, EINA_TRUE);
|
||||
eina_file_close_on_exec(pd->fd.out, EINA_TRUE);
|
||||
eina_file_close_on_exec(thdat->fd.in, EINA_TRUE);
|
||||
eina_file_close_on_exec(thdat->fd.out, EINA_TRUE);
|
||||
fcntl(pd->fd.in, F_SETFL, O_NONBLOCK);
|
||||
fcntl(pd->fd.out, F_SETFL, O_NONBLOCK);
|
||||
fcntl(thdat->fd.in, F_SETFL, O_NONBLOCK);
|
||||
fcntl(thdat->fd.out, F_SETFL, O_NONBLOCK);
|
||||
pd->fd.in_handler =
|
||||
efl_add(EFL_LOOP_HANDLER_CLASS, obj,
|
||||
efl_loop_handler_fd_set(efl_added, pd->fd.in),
|
||||
efl_event_callback_add
|
||||
(efl_added, EFL_LOOP_HANDLER_EVENT_WRITE, _cb_thread_parent_in, obj));
|
||||
pd->fd.out_handler =
|
||||
efl_add(EFL_LOOP_HANDLER_CLASS, obj,
|
||||
efl_loop_handler_fd_set(efl_added, pd->fd.out),
|
||||
efl_event_callback_add
|
||||
(efl_added, EFL_LOOP_HANDLER_EVENT_READ, _cb_thread_parent_out, obj));
|
||||
if (pd->read_listeners > 0)
|
||||
efl_loop_handler_active_set(pd->fd.out_handler, EFL_LOOP_HANDLER_FLAGS_READ);
|
||||
|
||||
if (pipe(pipe_to_thread) != 0)
|
||||
{
|
||||
ERR("Can't create to_thread control pipe");
|
||||
efl_del(pd->fd.in_handler);
|
||||
efl_del(pd->fd.out_handler);
|
||||
close(thdat->fd.in);
|
||||
close(thdat->fd.out);
|
||||
close(pd->fd.in);
|
||||
close(pd->fd.out);
|
||||
pd->fd.in_handler = NULL;
|
||||
pd->fd.out_handler = NULL;
|
||||
pd->fd.in = -1;
|
||||
pd->fd.out = -1;
|
||||
free(thdat);
|
||||
return EINA_FALSE;
|
||||
}
|
||||
if (pipe(pipe_from_thread) != 0)
|
||||
{
|
||||
ERR("Can't create from_thread control pipe");
|
||||
efl_del(pd->fd.in_handler);
|
||||
efl_del(pd->fd.out_handler);
|
||||
close(pipe_to_thread[0]);
|
||||
close(pipe_to_thread[1]);
|
||||
close(thdat->fd.in);
|
||||
close(thdat->fd.out);
|
||||
close(pd->fd.in);
|
||||
close(pd->fd.out);
|
||||
pd->fd.in_handler = NULL;
|
||||
pd->fd.out_handler = NULL;
|
||||
pd->fd.in = -1;
|
||||
pd->fd.out = -1;
|
||||
free(thdat);
|
||||
return EINA_FALSE;
|
||||
}
|
||||
thdat->ctrl.in = pipe_from_thread[1]; // write - input to parent
|
||||
thdat->ctrl.out = pipe_to_thread [0]; // read - output from parent
|
||||
pd->ctrl.in = pipe_to_thread [1]; // write - input to child
|
||||
pd->ctrl.out = pipe_from_thread[0]; // read - output from child
|
||||
// yes - these are blocking because we write and read very little
|
||||
eina_file_close_on_exec(pd->ctrl.in, EINA_TRUE);
|
||||
eina_file_close_on_exec(pd->ctrl.out, EINA_TRUE);
|
||||
eina_file_close_on_exec(thdat->ctrl.in, EINA_TRUE);
|
||||
eina_file_close_on_exec(thdat->ctrl.out, EINA_TRUE);
|
||||
pd->ctrl.in_handler =
|
||||
efl_add(EFL_LOOP_HANDLER_CLASS, obj,
|
||||
efl_loop_handler_fd_set(efl_added, pd->ctrl.in));
|
||||
pd->ctrl.out_handler =
|
||||
efl_add(EFL_LOOP_HANDLER_CLASS, obj,
|
||||
efl_loop_handler_fd_set(efl_added, pd->ctrl.out),
|
||||
efl_event_callback_add
|
||||
(efl_added, EFL_LOOP_HANDLER_EVENT_READ, _cb_thread_parent_ctrl_out, obj),
|
||||
efl_loop_handler_active_set
|
||||
(efl_added, EFL_LOOP_HANDLER_FLAGS_READ));
|
||||
|
||||
switch (efl_task_priority_get(obj))
|
||||
{
|
||||
case EFL_TASK_PRIORITY_BACKGROUND:
|
||||
pri = EINA_THREAD_IDLE;
|
||||
break;
|
||||
case EFL_TASK_PRIORITY_HIGH:
|
||||
case EFL_TASK_PRIORITY_ULTRA:
|
||||
pri = EINA_THREAD_URGENT;
|
||||
break;
|
||||
case EFL_TASK_PRIORITY_LOW:
|
||||
pri = EINA_THREAD_BACKGROUND;
|
||||
break;
|
||||
case EFL_TASK_PRIORITY_NORMAL:
|
||||
default:
|
||||
pri = EINA_THREAD_NORMAL;
|
||||
break;
|
||||
}
|
||||
name = efl_name_get(obj);
|
||||
if (name) thdat->name = eina_stringshare_add(name);
|
||||
|
||||
argc = efl_task_arg_count_get(obj);
|
||||
if (argc > 0)
|
||||
{
|
||||
thdat->args.argc = argc;
|
||||
thdat->args.argv = malloc(argc * sizeof(char *));
|
||||
if (thdat->args.argv)
|
||||
{
|
||||
for (i = 0; i < argc; i++)
|
||||
{
|
||||
const char *argv = efl_task_arg_value_get(obj, i);
|
||||
if (argv)
|
||||
thdat->args.argv[i] = eina_stringshare_add(argv);
|
||||
else
|
||||
thdat->args.argv[i] = NULL;
|
||||
}
|
||||
}
|
||||
// XXX: if malloc fails?
|
||||
}
|
||||
if (pd->event_cb)
|
||||
{
|
||||
num = 0;
|
||||
for (it = pd->event_cb; it->func; it++) num++;
|
||||
thdat->event_cb = malloc((num + 1) * sizeof(Efl_Callback_Array_Item_Full));
|
||||
if (thdat->event_cb)
|
||||
memcpy(thdat->event_cb, pd->event_cb,
|
||||
(num + 1) * sizeof(Efl_Callback_Array_Item_Full));
|
||||
// XXX: if malloc fails?
|
||||
}
|
||||
|
||||
// env data - ignore as other end will share same env
|
||||
|
||||
if (!eina_thread_create(&(pd->thread), pri, -1, _efl_thread_main, thdat))
|
||||
{
|
||||
for (i = 0; i < thdat->args.argc; i++)
|
||||
eina_stringshare_del(thdat->args.argv[i]);
|
||||
free(thdat->args.argv);
|
||||
efl_del(pd->fd.in_handler);
|
||||
efl_del(pd->fd.out_handler);
|
||||
efl_del(pd->ctrl.in_handler);
|
||||
efl_del(pd->ctrl.out_handler);
|
||||
close(pd->fd.in);
|
||||
close(pd->fd.out);
|
||||
close(pd->ctrl.in);
|
||||
close(pd->ctrl.out);
|
||||
close(thdat->fd.in);
|
||||
close(thdat->fd.out);
|
||||
close(thdat->ctrl.in);
|
||||
close(thdat->ctrl.out);
|
||||
free(thdat);
|
||||
pd->fd.in_handler = NULL;
|
||||
pd->fd.out_handler = NULL;
|
||||
pd->ctrl.in_handler = NULL;
|
||||
pd->ctrl.out_handler = NULL;
|
||||
pd->fd.in = -1;
|
||||
pd->fd.out = -1;
|
||||
pd->ctrl.in = -1;
|
||||
pd->ctrl.out = -1;
|
||||
return EINA_FALSE;
|
||||
}
|
||||
pd->thdat = thdat;
|
||||
return EINA_TRUE;
|
||||
}
|
||||
|
||||
EOLIAN static void
|
||||
_efl_thread_efl_task_end(Eo *obj EINA_UNUSED, Efl_Thread_Data *pd)
|
||||
{
|
||||
if (pd->end_sent) return;
|
||||
if (pd->thdat)
|
||||
{
|
||||
Control_Data cmd;
|
||||
|
||||
pd->end_sent = EINA_TRUE;
|
||||
cmd.command = CMD_EXIT;
|
||||
cmd.data = 0;
|
||||
write(pd->ctrl.in, &cmd, sizeof(Control_Data));
|
||||
}
|
||||
}
|
||||
|
||||
EOLIAN static Eina_Error
|
||||
_efl_thread_efl_io_closer_close(Eo *obj, Efl_Thread_Data *pd)
|
||||
{
|
||||
if (!pd->thdat) return 0;
|
||||
EINA_SAFETY_ON_TRUE_RETURN_VAL(efl_io_closer_closed_get(obj), EBADF);
|
||||
efl_io_writer_can_write_set(obj, EINA_FALSE);
|
||||
efl_io_reader_can_read_set(obj, EINA_FALSE);
|
||||
efl_io_reader_eos_set(obj, EINA_TRUE);
|
||||
if (pd->fd.in >= 0) close(pd->fd.in);
|
||||
if (pd->fd.out >= 0) close(pd->fd.out);
|
||||
if (pd->fd.in_handler) efl_del(pd->fd.in_handler);
|
||||
if (pd->fd.out_handler) efl_del(pd->fd.out_handler);
|
||||
pd->fd.in = -1;
|
||||
pd->fd.out = -1;
|
||||
pd->fd.in_handler = NULL;
|
||||
pd->fd.out_handler = NULL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
EOLIAN static Eina_Bool
|
||||
_efl_thread_efl_io_closer_closed_get(Eo *obj EINA_UNUSED, Efl_Thread_Data *pd)
|
||||
{
|
||||
if ((pd->fd.in == -1) && (pd->fd.out == -1)) return EINA_TRUE;
|
||||
return EINA_FALSE;
|
||||
}
|
||||
|
||||
EOLIAN static Eina_Error
|
||||
_efl_thread_efl_io_reader_read(Eo *obj, Efl_Thread_Data *pd, Eina_Rw_Slice *rw_slice)
|
||||
{
|
||||
ssize_t r;
|
||||
|
||||
errno = 0;
|
||||
if (pd->fd.out == -1) goto err;
|
||||
|
||||
do
|
||||
{
|
||||
errno = 0;
|
||||
r = read(pd->fd.out, rw_slice->mem, rw_slice->len);
|
||||
if (r == -1)
|
||||
{
|
||||
if (errno == EINTR) continue;
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
while (r == -1);
|
||||
|
||||
rw_slice->len = r;
|
||||
if (r == 0)
|
||||
{
|
||||
efl_io_reader_can_read_set(obj, EINA_FALSE);
|
||||
efl_io_reader_eos_set(obj, EINA_TRUE);
|
||||
close(pd->fd.out);
|
||||
pd->fd.out = -1;
|
||||
efl_del(pd->fd.out_handler);
|
||||
pd->fd.out_handler = NULL;
|
||||
_thread_exit_eval(obj, pd);
|
||||
return EPIPE;
|
||||
}
|
||||
return 0;
|
||||
err:
|
||||
if ((pd->fd.out != -1) && (errno != EAGAIN))
|
||||
{
|
||||
close(pd->fd.out);
|
||||
pd->fd.out = -1;
|
||||
efl_del(pd->fd.out_handler);
|
||||
pd->fd.out_handler = NULL;
|
||||
}
|
||||
rw_slice->len = 0;
|
||||
rw_slice->mem = NULL;
|
||||
efl_io_reader_can_read_set(obj, EINA_FALSE);
|
||||
_thread_exit_eval(obj, pd);
|
||||
return EINVAL;
|
||||
}
|
||||
|
||||
EOLIAN static void
|
||||
_efl_thread_efl_io_reader_can_read_set(Eo *obj, Efl_Thread_Data *pd, Eina_Bool can_read)
|
||||
{
|
||||
Eina_Bool old = efl_io_reader_can_read_get(obj);
|
||||
if (old == can_read) return;
|
||||
pd->fd.can_read = can_read;
|
||||
if (!pd->fd.out_handler) return;
|
||||
if (can_read)
|
||||
efl_loop_handler_active_set(pd->fd.out_handler, 0);
|
||||
else
|
||||
efl_loop_handler_active_set(pd->fd.out_handler,
|
||||
EFL_LOOP_HANDLER_FLAGS_READ);
|
||||
efl_event_callback_call(obj, EFL_IO_READER_EVENT_CAN_READ_CHANGED, NULL);
|
||||
}
|
||||
|
||||
EOLIAN static Eina_Bool
|
||||
_efl_thread_efl_io_reader_can_read_get(Eo *obj EINA_UNUSED, Efl_Thread_Data *pd)
|
||||
{
|
||||
return pd->fd.can_read;
|
||||
}
|
||||
|
||||
EOLIAN static void
|
||||
_efl_thread_efl_io_reader_eos_set(Eo *obj, Efl_Thread_Data *pd, Eina_Bool is_eos)
|
||||
{
|
||||
Eina_Bool old = efl_io_reader_eos_get(obj);
|
||||
if (old == is_eos) return;
|
||||
|
||||
pd->fd.eos_read = is_eos;
|
||||
if (!is_eos) return;
|
||||
if (pd->fd.out_handler)
|
||||
efl_loop_handler_active_set(pd->fd.out_handler, 0);
|
||||
efl_event_callback_call(obj, EFL_IO_READER_EVENT_EOS, NULL);
|
||||
}
|
||||
|
||||
EOLIAN static Eina_Bool
|
||||
_efl_thread_efl_io_reader_eos_get(Eo *obj EINA_UNUSED, Efl_Thread_Data *pd)
|
||||
{
|
||||
return pd->fd.eos_read;
|
||||
}
|
||||
|
||||
EOLIAN static Eina_Error
|
||||
_efl_thread_efl_io_writer_write(Eo *obj, Efl_Thread_Data *pd, Eina_Slice *slice, Eina_Slice *remaining)
|
||||
{
|
||||
ssize_t r;
|
||||
|
||||
errno = 0;
|
||||
if (pd->fd.in == -1) goto err;
|
||||
|
||||
do
|
||||
{
|
||||
errno = 0;
|
||||
r = write(pd->fd.in, slice->mem, slice->len);
|
||||
if (r == -1)
|
||||
{
|
||||
if (errno == EINTR) continue;
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
while (r == -1);
|
||||
|
||||
if (remaining)
|
||||
{
|
||||
remaining->len = slice->len - r;
|
||||
remaining->bytes = slice->bytes + r;
|
||||
}
|
||||
slice->len = r;
|
||||
|
||||
if ((slice) && (slice->len > 0))
|
||||
efl_io_writer_can_write_set(obj, EINA_FALSE);
|
||||
if (r == 0)
|
||||
{
|
||||
close(pd->fd.in);
|
||||
pd->fd.in = -1;
|
||||
efl_del(pd->fd.in_handler);
|
||||
pd->fd.in_handler = NULL;
|
||||
_thread_exit_eval(obj, pd);
|
||||
return EPIPE;
|
||||
}
|
||||
return 0;
|
||||
err:
|
||||
if ((pd->fd.in != -1) && (errno != EAGAIN))
|
||||
{
|
||||
close(pd->fd.in);
|
||||
pd->fd.in = -1;
|
||||
efl_del(pd->fd.in_handler);
|
||||
pd->fd.in_handler = NULL;
|
||||
}
|
||||
if (remaining) *remaining = *slice;
|
||||
slice->len = 0;
|
||||
slice->mem = NULL;
|
||||
efl_io_writer_can_write_set(obj, EINA_FALSE);
|
||||
_thread_exit_eval(obj, pd);
|
||||
return EINVAL;
|
||||
}
|
||||
|
||||
EOLIAN static void
|
||||
_efl_thread_efl_io_writer_can_write_set(Eo *obj, Efl_Thread_Data *pd, Eina_Bool can_write)
|
||||
{
|
||||
Eina_Bool old = efl_io_writer_can_write_get(obj);
|
||||
if (old == can_write) return;
|
||||
pd->fd.can_write = can_write;
|
||||
if (can_write)
|
||||
efl_loop_handler_active_set(pd->fd.in_handler, 0);
|
||||
else
|
||||
efl_loop_handler_active_set(pd->fd.in_handler,
|
||||
EFL_LOOP_HANDLER_FLAGS_WRITE);
|
||||
efl_event_callback_call(obj, EFL_IO_WRITER_EVENT_CAN_WRITE_CHANGED, NULL);
|
||||
}
|
||||
|
||||
EOLIAN static Eina_Bool
|
||||
_efl_thread_efl_io_writer_can_write_get(Eo *obj EINA_UNUSED, Efl_Thread_Data *pd)
|
||||
{
|
||||
return pd->fd.can_write;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "efl_thread.eo.c"
|
|
@ -8,5 +8,15 @@ class Efl.Thread (Efl.Task)
|
|||
implements {
|
||||
Efl.Object.constructor;
|
||||
Efl.Object.destructor;
|
||||
Efl.Object.parent { set; }
|
||||
Efl.Task.run;
|
||||
Efl.Task.end;
|
||||
Efl.Io.Closer.close;
|
||||
Efl.Io.Closer.closed { get; }
|
||||
Efl.Io.Reader.read;
|
||||
Efl.Io.Reader.can_read { get; set; }
|
||||
Efl.Io.Reader.eos { get; set; }
|
||||
Efl.Io.Writer.write;
|
||||
Efl.Io.Writer.can_write { get; set; }
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3195,7 +3195,7 @@ _ecore_evas_animator_fallback(void *data)
|
|||
static void
|
||||
_check_animator_event_catcher_add(void *data, const Efl_Event *event)
|
||||
{
|
||||
const Efl_Callback_Array_Item *array = event->info;
|
||||
const Efl_Callback_Array_Item_Full *array = event->info;
|
||||
Ecore_Evas *ee = data;
|
||||
int i;
|
||||
|
||||
|
@ -3229,7 +3229,7 @@ _check_animator_event_catcher_add(void *data, const Efl_Event *event)
|
|||
static void
|
||||
_check_animator_event_catcher_del(void *data, const Efl_Event *event)
|
||||
{
|
||||
const Efl_Callback_Array_Item *array = event->info;
|
||||
const Efl_Callback_Array_Item_Full *array = event->info;
|
||||
Ecore_Evas *ee = data;
|
||||
int i;
|
||||
|
||||
|
|
|
@ -71,6 +71,8 @@ struct _Eina_Vpath_Interface_User
|
|||
*/
|
||||
EAPI void __eina_promise_cancel_all(void);
|
||||
|
||||
EAPI void __eina_promise_cancel_data(void *data);
|
||||
|
||||
/**
|
||||
* Make the app specific paths accessable as virtual path
|
||||
*
|
||||
|
|
|
@ -566,6 +566,27 @@ __eina_promise_cancel_all(void)
|
|||
eina_lock_release(&_pending_futures_lock);
|
||||
}
|
||||
|
||||
EAPI void
|
||||
__eina_promise_cancel_data(void *data)
|
||||
{
|
||||
Eina_List *del = NULL, *l;
|
||||
Eina_Future *f;
|
||||
|
||||
eina_lock_take(&_pending_futures_lock);
|
||||
EINA_LIST_FOREACH(_pending_futures, l, f)
|
||||
{
|
||||
if (f->data == data)
|
||||
{
|
||||
del = eina_list_append(del, f);
|
||||
}
|
||||
}
|
||||
EINA_LIST_FREE(del, f)
|
||||
{
|
||||
_eina_future_cancel(f, ECANCELED);
|
||||
}
|
||||
eina_lock_release(&_pending_futures_lock);
|
||||
}
|
||||
|
||||
Eina_Bool
|
||||
eina_promise_shutdown(void)
|
||||
{
|
||||
|
|
|
@ -2975,9 +2975,10 @@ _efl_ui_text_efl_canvas_group_group_member_add(Eo *obj, Efl_Ui_Text_Data *sd, Ev
|
|||
static void
|
||||
_cb_added(void *data EINA_UNUSED, const Efl_Event *ev)
|
||||
{
|
||||
const Efl_Callback_Array_Item *event = ev->info;
|
||||
const Efl_Callback_Array_Item_Full *event = ev->info;
|
||||
|
||||
EFL_UI_TEXT_DATA_GET(ev->object, sd);
|
||||
// XXX: BUG - not walking the array until a NULL entry
|
||||
if (event->desc == EFL_UI_TEXT_EVENT_VALIDATE)
|
||||
sd->validators++;
|
||||
}
|
||||
|
@ -2985,9 +2986,10 @@ _cb_added(void *data EINA_UNUSED, const Efl_Event *ev)
|
|||
static void
|
||||
_cb_deleted(void *data EINA_UNUSED, const Efl_Event *ev)
|
||||
{
|
||||
const Efl_Callback_Array_Item *event = ev->info;
|
||||
const Efl_Callback_Array_Item_Full *event = ev->info;
|
||||
|
||||
EFL_UI_TEXT_DATA_GET(ev->object, sd);
|
||||
// XXX: BUG - not walking the array until a NULL entry
|
||||
if (event->desc == EFL_UI_TEXT_EVENT_VALIDATE)
|
||||
sd->validators--;
|
||||
return;
|
||||
|
|
|
@ -1904,7 +1904,7 @@ _elm_win_evas_device_changed(void *data,
|
|||
static void
|
||||
_win_event_add_cb(void *data, const Efl_Event *ev)
|
||||
{
|
||||
const Efl_Callback_Array_Item *array = ev->info;
|
||||
const Efl_Callback_Array_Item_Full *array = ev->info;
|
||||
Efl_Ui_Win_Data *sd = data;
|
||||
Efl_Ui_Win *win = ev->object;
|
||||
int i;
|
||||
|
@ -2035,7 +2035,7 @@ _win_event_add_cb(void *data, const Efl_Event *ev)
|
|||
static void
|
||||
_win_event_del_cb(void *data, const Efl_Event *ev)
|
||||
{
|
||||
const Efl_Callback_Array_Item *array = ev->info;
|
||||
const Efl_Callback_Array_Item_Full *array = ev->info;
|
||||
Efl_Ui_Win_Data *sd = data;
|
||||
Efl_Ui_Win *win = ev->object;
|
||||
int i;
|
||||
|
@ -2177,7 +2177,7 @@ _win_paused(void *data, const Efl_Event *ev)
|
|||
_paused_windows++;
|
||||
|
||||
if (_elm_win_count == _paused_windows)
|
||||
efl_event_callback_call(efl_loop_get(ev->object), EFL_LOOP_EVENT_PAUSE, NULL);
|
||||
efl_event_callback_call(efl_loop_get(ev->object), EFL_APP_EVENT_PAUSE, NULL);
|
||||
}
|
||||
|
||||
EFL_CALLBACKS_ARRAY_DEFINE(_elm_win_tracking,
|
||||
|
@ -2205,7 +2205,7 @@ _elm_win_resume(void *data, const Efl_Event *ev)
|
|||
sd->paused = EINA_FALSE;
|
||||
|
||||
if (_elm_win_count == _paused_windows)
|
||||
efl_event_callback_call(efl_loop_get(ev->object), EFL_LOOP_EVENT_RESUME, NULL);
|
||||
efl_event_callback_call(efl_loop_get(ev->object), EFL_APP_EVENT_RESUME, NULL);
|
||||
|
||||
_paused_windows--;
|
||||
}
|
||||
|
@ -2831,7 +2831,7 @@ _efl_ui_win_efl_canvas_group_group_del(Eo *obj, Efl_Ui_Win_Data *sd)
|
|||
_elm_win_state_eval_queue();
|
||||
|
||||
if (_elm_win_count == _paused_windows)
|
||||
efl_event_callback_call(efl_loop_get(obj), EFL_LOOP_EVENT_PAUSE, NULL);
|
||||
efl_event_callback_call(efl_loop_get(obj), EFL_APP_EVENT_PAUSE, NULL);
|
||||
|
||||
if (sd->ee)
|
||||
{
|
||||
|
@ -5474,7 +5474,7 @@ _efl_ui_win_efl_object_finalize(Eo *obj, Efl_Ui_Win_Data *sd)
|
|||
obj = _elm_win_finalize_internal(obj, sd, sd->name, sd->type);
|
||||
if (!obj) return NULL;
|
||||
obj = efl_finalize(efl_super(obj, MY_CLASS));
|
||||
if (obj && resume) efl_event_callback_call(efl_loop_get(obj), EFL_LOOP_EVENT_RESUME, NULL);
|
||||
if (obj && resume) efl_event_callback_call(efl_loop_get(obj), EFL_APP_EVENT_RESUME, NULL);
|
||||
return obj;
|
||||
}
|
||||
|
||||
|
|
|
@ -4061,9 +4061,10 @@ elm_entry_add(Evas_Object *parent)
|
|||
static void
|
||||
_cb_added(void *data EINA_UNUSED, const Efl_Event *ev)
|
||||
{
|
||||
const Efl_Callback_Array_Item *event = ev->info;
|
||||
const Efl_Callback_Array_Item_Full *event = ev->info;
|
||||
|
||||
ELM_ENTRY_DATA_GET(ev->object, sd);
|
||||
// XXX: BUG - not walking the array until a NULL entry
|
||||
if (event->desc == ELM_ENTRY_EVENT_VALIDATE)
|
||||
sd->validators++;
|
||||
}
|
||||
|
@ -4071,9 +4072,10 @@ _cb_added(void *data EINA_UNUSED, const Efl_Event *ev)
|
|||
static void
|
||||
_cb_deleted(void *data EINA_UNUSED, const Efl_Event *ev)
|
||||
{
|
||||
const Efl_Callback_Array_Item *event = ev->info;
|
||||
const Efl_Callback_Array_Item_Full *event = ev->info;
|
||||
|
||||
ELM_ENTRY_DATA_GET(ev->object, sd);
|
||||
// XXX: BUG - not walking the array until a NULL entry
|
||||
if (event->desc == ELM_ENTRY_EVENT_VALIDATE)
|
||||
sd->validators--;
|
||||
return;
|
||||
|
|
|
@ -927,8 +927,8 @@ static void (*qre_terminate)(void *data,
|
|||
|
||||
EFL_CALLBACKS_ARRAY_DEFINE(_qre_main_ex,
|
||||
{ EFL_LOOP_EVENT_ARGUMENTS, qre_main },
|
||||
{ EFL_LOOP_EVENT_PAUSE, qre_pause },
|
||||
{ EFL_LOOP_EVENT_RESUME, qre_resume },
|
||||
{ EFL_APP_EVENT_PAUSE, qre_pause },
|
||||
{ EFL_APP_EVENT_RESUME, qre_resume },
|
||||
{ EFL_EVENT_DEL, qre_terminate });
|
||||
|
||||
EAPI Eina_Bool
|
||||
|
@ -1304,12 +1304,12 @@ elm_policy_set(unsigned int policy,
|
|||
{
|
||||
if (value == ELM_POLICY_EXIT_WINDOWS_DEL)
|
||||
{
|
||||
efl_event_callback_add(efl_main_loop_get(), EFL_LOOP_EVENT_TERMINATE,
|
||||
efl_event_callback_add(efl_main_loop_get(), EFL_APP_EVENT_TERMINATE,
|
||||
_on_terminate, NULL);
|
||||
}
|
||||
else
|
||||
{
|
||||
efl_event_callback_del(efl_main_loop_get(), EFL_LOOP_EVENT_TERMINATE,
|
||||
efl_event_callback_del(efl_main_loop_get(), EFL_APP_EVENT_TERMINATE,
|
||||
_on_terminate, NULL);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -241,10 +241,25 @@ typedef short Efl_Callback_Priority;
|
|||
*/
|
||||
typedef struct _Efl_Callback_Array_Item
|
||||
{
|
||||
const Efl_Event_Description *desc; /**< The event description. */
|
||||
Efl_Event_Cb func; /**< The callback function. */
|
||||
const Efl_Event_Description *desc; /**< The event description. */
|
||||
Efl_Event_Cb func; /**< The callback function. */
|
||||
} Efl_Callback_Array_Item;
|
||||
|
||||
|
||||
/**
|
||||
* @struct _Efl_Callback_Array_Item_Full
|
||||
* @brief An item provided by EFL_EVENT_CALLBACK_ADD/EFL_EVENT_CALLBACK_DEL.
|
||||
*
|
||||
* See also EFL_EVENT_CALLBACK_ADD EFL_EVENT_CALLBACK_DEL.
|
||||
*/
|
||||
typedef struct _Efl_Callback_Array_Item_Full
|
||||
{
|
||||
const Efl_Event_Description *desc; /**< The event description. */
|
||||
Efl_Callback_Priority priority; /** < The priorit of the event */
|
||||
Efl_Event_Cb func; /**< The callback function. */
|
||||
void *user_data; /**< The user data pointer to be passed to the func */
|
||||
} Efl_Callback_Array_Item_Full;
|
||||
|
||||
/**
|
||||
* @brief Add a callback for an event with a specific priority.
|
||||
*
|
||||
|
|
|
@ -1228,7 +1228,8 @@ _efl_object_event_callback_priority_add(Eo *obj, Efl_Object_Data *pd,
|
|||
Efl_Event_Cb func,
|
||||
const void *user_data)
|
||||
{
|
||||
const Efl_Callback_Array_Item arr[] = { {desc, func}, {NULL, NULL}};
|
||||
const Efl_Callback_Array_Item_Full arr[] =
|
||||
{ {desc, priority, func, (void *)user_data}, {NULL, 0, NULL, NULL}};
|
||||
Eo_Callback_Description *cb = _eo_callback_new();
|
||||
|
||||
// very unlikely so improve l1 instr cache by using goto
|
||||
|
@ -1265,7 +1266,7 @@ EOAPI EFL_FUNC_BODYV(efl_event_callback_priority_add,
|
|||
|
||||
static void
|
||||
_efl_object_event_callback_clean(Eo *obj, Efl_Object_Data *pd,
|
||||
const Efl_Callback_Array_Item *array,
|
||||
const Efl_Callback_Array_Item_Full *array,
|
||||
Eo_Callback_Description **cb)
|
||||
{
|
||||
(*cb)->delete_me = EINA_TRUE;
|
||||
|
@ -1295,7 +1296,8 @@ _efl_object_event_callback_del(Eo *obj, Efl_Object_Data *pd,
|
|||
((*cb)->items.item.func == func) &&
|
||||
((*cb)->func_data == user_data))
|
||||
{
|
||||
const Efl_Callback_Array_Item arr[] = { {desc, func}, {NULL, NULL}};
|
||||
const Efl_Callback_Array_Item_Full arr[] =
|
||||
{ {desc, (*cb)->priority, func, (*cb)->func_data}, {NULL, 0, NULL, NULL}};
|
||||
|
||||
_efl_object_event_callback_clean(obj, pd, arr, cb);
|
||||
return EINA_TRUE;
|
||||
|
@ -1318,9 +1320,9 @@ _efl_object_event_callback_array_priority_add(Eo *obj, Efl_Object_Data *pd,
|
|||
const void *user_data)
|
||||
{
|
||||
Eo_Callback_Description *cb = _eo_callback_new();
|
||||
#if defined(EFL_EVENT_SPECIAL_SKIP) || defined(EO_DEBUG)
|
||||
const Efl_Callback_Array_Item *it;
|
||||
#endif
|
||||
unsigned int num, i;
|
||||
Efl_Callback_Array_Item_Full *ev_array;
|
||||
#ifdef EO_DEBUG
|
||||
const Efl_Callback_Array_Item *prev;
|
||||
#endif
|
||||
|
@ -1363,7 +1365,21 @@ _efl_object_event_callback_array_priority_add(Eo *obj, Efl_Object_Data *pd,
|
|||
}
|
||||
#endif
|
||||
|
||||
efl_event_callback_call(obj, EFL_EVENT_CALLBACK_ADD, (void *)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_event_callback_call(obj, EFL_EVENT_CALLBACK_ADD, ev_array);
|
||||
|
||||
return EINA_TRUE;
|
||||
|
||||
|
@ -1384,17 +1400,35 @@ _efl_object_event_callback_array_del(Eo *obj, Efl_Object_Data *pd,
|
|||
const void *user_data)
|
||||
{
|
||||
Eo_Callback_Description **cb;
|
||||
unsigned int i;
|
||||
unsigned int j;
|
||||
|
||||
for (cb = pd->callbacks, i = 0;
|
||||
i < pd->callbacks_count;
|
||||
cb++, i++)
|
||||
for (cb = pd->callbacks, j = 0;
|
||||
j < pd->callbacks_count;
|
||||
cb++, j++)
|
||||
{
|
||||
if (!(*cb)->delete_me &&
|
||||
((*cb)->items.item_array == array) &&
|
||||
((*cb)->func_data == user_data))
|
||||
{
|
||||
_efl_object_event_callback_clean(obj, pd, array, cb);
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -700,7 +700,7 @@ _animator_repeater(void *data, const Efl_Event *event)
|
|||
static void
|
||||
_check_event_catcher_add(void *data, const Efl_Event *event)
|
||||
{
|
||||
const Efl_Callback_Array_Item *array = event->info;
|
||||
const Efl_Callback_Array_Item_Full *array = event->info;
|
||||
Evas_Object_Protected_Data *obj = data;
|
||||
Evas_Callback_Type type = EVAS_CALLBACK_LAST;
|
||||
int i;
|
||||
|
@ -728,7 +728,7 @@ _check_event_catcher_add(void *data, const Efl_Event *event)
|
|||
static void
|
||||
_check_event_catcher_del(void *data, const Efl_Event *event)
|
||||
{
|
||||
const Efl_Callback_Array_Item *array = event->info;
|
||||
const Efl_Callback_Array_Item_Full *array = event->info;
|
||||
Evas_Object_Protected_Data *obj = data;
|
||||
int i;
|
||||
|
||||
|
|
|
@ -896,11 +896,11 @@ START_TEST(ecore_test_efl_app_version)
|
|||
|
||||
ecore_init();
|
||||
|
||||
loop = efl_loop_main_get(EFL_LOOP_CLASS);
|
||||
loop = efl_app_loop_main_get(EFL_APP_CLASS);
|
||||
fail_if(!efl_isa(loop, EFL_LOOP_CLASS));
|
||||
|
||||
efl_build_version_set(EFL_VERSION_MAJOR, EFL_VERSION_MINOR, 0, 0, NULL, EFL_BUILD_ID);
|
||||
ver = efl_loop_app_efl_version_get(loop);
|
||||
ver = efl_app_build_efl_version_get(loop);
|
||||
fail_if(!ver);
|
||||
fail_if(ver->major != EFL_VERSION_MAJOR);
|
||||
fail_if(ver->minor != EFL_VERSION_MINOR);
|
||||
|
@ -909,7 +909,7 @@ START_TEST(ecore_test_efl_app_version)
|
|||
fail_if(ver->flavor);
|
||||
fail_if(!eina_streq(ver->build_id, EFL_BUILD_ID));
|
||||
|
||||
ver = efl_loop_efl_version_get(loop);
|
||||
ver = efl_app_efl_version_get(loop);
|
||||
fail_if(!ver);
|
||||
fail_if(ver->major != EFL_VERSION_MAJOR);
|
||||
fail_if(ver->minor != EFL_VERSION_MINOR);
|
||||
|
|
|
@ -32,10 +32,10 @@ START_TEST(efl_ui_test_init)
|
|||
_efl_startup_time = ecore_time_unix_get();
|
||||
_EFL_APP_VERSION_SET();
|
||||
fail_if(!ecore_init());
|
||||
efl_event_callback_add(efl_app_main_loop_get(efl_app_get()), EFL_LOOP_EVENT_ARGUMENTS, efl_main, NULL);
|
||||
efl_event_callback_add(efl_app_get(), EFL_LOOP_EVENT_ARGUMENTS, efl_main, NULL);
|
||||
fail_if(!ecore_init_ex(argc, argv));
|
||||
__EFL_MAIN_CONSTRUCTOR;
|
||||
ret__ = efl_loop_begin(efl_app_main_loop_get(efl_app_get()));
|
||||
ret__ = efl_loop_begin(efl_app_get());
|
||||
real__ = efl_loop_exit_code_process(ret__);
|
||||
__EFL_MAIN_DESTRUCTOR;
|
||||
ecore_shutdown_ex();
|
||||
|
|
|
@ -32,7 +32,7 @@ void
|
|||
_cb_added(void *data EINA_UNUSED, const Efl_Event *event)
|
||||
{
|
||||
Simple_Public_Data *pd = efl_data_scope_get(event->object, MY_CLASS);
|
||||
const Efl_Callback_Array_Item *callback_array = event->info;
|
||||
const Efl_Callback_Array_Item_Full *callback_array = event->info;
|
||||
|
||||
if (callback_array->desc != EV_A_CHANGED)
|
||||
return;
|
||||
|
@ -46,7 +46,7 @@ void
|
|||
_cb_deled(void *data EINA_UNUSED, const Efl_Event *event)
|
||||
{
|
||||
Simple_Public_Data *pd = efl_data_scope_get(event->object, MY_CLASS);
|
||||
const Efl_Callback_Array_Item *callback_array = event->info;
|
||||
const Efl_Callback_Array_Item_Full *callback_array = event->info;
|
||||
|
||||
if (callback_array->desc != EV_A_CHANGED)
|
||||
return;
|
||||
|
|
|
@ -181,11 +181,9 @@ _eo_signals_efl_del_cb(void *_data EINA_UNUSED, const Efl_Event *event EINA_UNUS
|
|||
void
|
||||
_eo_signals_cb_added_deled(void *data, const Efl_Event *event)
|
||||
{
|
||||
const Efl_Callback_Array_Item *callback_array = event->info;
|
||||
const Efl_Callback_Array_Item *(*callback_data)(void) = data;
|
||||
const Efl_Callback_Array_Item_Full *callback_array = event->info;
|
||||
|
||||
fail_if((callback_data() != callback_array) &&
|
||||
(callback_array->func != _eo_signals_cb_added_deled));
|
||||
fail_if(callback_array->func != _eo_signals_cb_added_deled);
|
||||
}
|
||||
|
||||
EFL_CALLBACKS_ARRAY_DEFINE(_eo_signals_callbacks,
|
||||
|
|
Loading…
Reference in New Issue