summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorCarsten Haitzler (Rasterman) <raster@rasterman.com>2018-02-27 21:19:17 +0900
committerCarsten Haitzler (Rasterman) <raster@rasterman.com>2018-03-03 13:40:33 +0900
commit1bdd9e4dd15fc27da43b50fd29bfb1b0b30ef6bd (patch)
tree168b9a7e716a814e8cdc476be53c61565a47ff3b /src
parent1c74aaa7e9c9fa1732b467aca5ee1458e3721f0a (diff)
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/
Diffstat (limited to '')
-rw-r--r--src/Makefile_Ecore.am9
-rw-r--r--src/lib/ecore/Ecore_Eo.h4
-rw-r--r--src/lib/ecore/ecore.c10
-rw-r--r--src/lib/ecore/ecore_exe.c2
-rw-r--r--src/lib/ecore/ecore_main.c8
-rw-r--r--src/lib/ecore/ecore_private.h17
-rw-r--r--src/lib/ecore/ecore_signal.c9
-rw-r--r--src/lib/ecore/ecore_timer.c4
-rw-r--r--src/lib/ecore/efl_app.c415
-rw-r--r--src/lib/ecore/efl_app.eo57
-rw-r--r--src/lib/ecore/efl_appthread.c245
-rw-r--r--src/lib/ecore/efl_appthread.eo22
-rw-r--r--src/lib/ecore/efl_exe.c28
-rw-r--r--src/lib/ecore/efl_general.h6
-rw-r--r--src/lib/ecore/efl_loop.c94
-rw-r--r--src/lib/ecore/efl_loop.eo36
-rw-r--r--src/lib/ecore/efl_loop_fd.c4
-rw-r--r--src/lib/ecore/efl_loop_handler.c2
-rw-r--r--src/lib/ecore/efl_task.c11
-rw-r--r--src/lib/ecore/efl_thread.c917
-rw-r--r--src/lib/ecore/efl_thread.eo10
-rw-r--r--src/lib/ecore_evas/ecore_evas.c4
-rw-r--r--src/lib/eina/eina_internal.h2
-rw-r--r--src/lib/eina/eina_promise.c21
-rw-r--r--src/lib/elementary/efl_ui_text.c6
-rw-r--r--src/lib/elementary/efl_ui_win.c12
-rw-r--r--src/lib/elementary/elm_entry.c6
-rw-r--r--src/lib/elementary/elm_main.c8
-rw-r--r--src/lib/eo/Eo.h19
-rw-r--r--src/lib/eo/eo_base_class.c56
-rw-r--r--src/lib/evas/canvas/evas_callbacks.c4
-rw-r--r--src/tests/ecore/ecore_test_ecore.c6
-rw-r--r--src/tests/elementary/efl_ui_suite.c4
-rw-r--r--src/tests/eo/signals/signals_simple.c4
-rw-r--r--src/tests/eo/suite/eo_test_general.c6
35 files changed, 1882 insertions, 186 deletions
diff --git a/src/Makefile_Ecore.am b/src/Makefile_Ecore.am
index 28a46d374d..630977846d 100644
--- a/src/Makefile_Ecore.am
+++ b/src/Makefile_Ecore.am
@@ -8,6 +8,7 @@ ecore_eolian_files_legacy = \
8 lib/ecore/efl_loop_timer.eo 8 lib/ecore/efl_loop_timer.eo
9 9
10ecore_eolian_files_public = \ 10ecore_eolian_files_public = \
11 lib/ecore/efl_app.eo \
11 lib/ecore/efl_loop.eo \ 12 lib/ecore/efl_loop.eo \
12 lib/ecore/efl_loop_consumer.eo \ 13 lib/ecore/efl_loop_consumer.eo \
13 lib/ecore/efl_loop_fd.eo \ 14 lib/ecore/efl_loop_fd.eo \
@@ -16,6 +17,8 @@ ecore_eolian_files_public = \
16 lib/ecore/efl_loop_message_handler.eo \ 17 lib/ecore/efl_loop_message_handler.eo \
17 lib/ecore/efl_exe.eo \ 18 lib/ecore/efl_exe.eo \
18 lib/ecore/efl_thread.eo \ 19 lib/ecore/efl_thread.eo \
20 lib/ecore/efl_appthread.eo \
21 lib/ecore/efl_task.eo \
19 lib/ecore/efl_io_closer_fd.eo \ 22 lib/ecore/efl_io_closer_fd.eo \
20 lib/ecore/efl_io_positioner_fd.eo \ 23 lib/ecore/efl_io_positioner_fd.eo \
21 lib/ecore/efl_io_reader_fd.eo \ 24 lib/ecore/efl_io_reader_fd.eo \
@@ -35,8 +38,7 @@ ecore_eolian_files_public = \
35 lib/ecore/efl_interpolator_divisor.eo \ 38 lib/ecore/efl_interpolator_divisor.eo \
36 lib/ecore/efl_interpolator_bounce.eo \ 39 lib/ecore/efl_interpolator_bounce.eo \
37 lib/ecore/efl_interpolator_spring.eo \ 40 lib/ecore/efl_interpolator_spring.eo \
38 lib/ecore/efl_interpolator_cubic_bezier.eo \ 41 lib/ecore/efl_interpolator_cubic_bezier.eo
39 lib/ecore/efl_task.eo
40 42
41ecore_eolian_files = \ 43ecore_eolian_files = \
42 $(ecore_eolian_files_public) \ 44 $(ecore_eolian_files_public) \
@@ -95,6 +97,7 @@ lib/ecore/ecore_job.c \
95lib/ecore/ecore_main.c \ 97lib/ecore/ecore_main.c \
96lib/ecore/ecore_event_message.c \ 98lib/ecore/ecore_event_message.c \
97lib/ecore/ecore_event_message_handler.c \ 99lib/ecore/ecore_event_message_handler.c \
100lib/ecore/efl_app.c \
98lib/ecore/efl_loop.c \ 101lib/ecore/efl_loop.c \
99lib/ecore/efl_loop_consumer.c \ 102lib/ecore/efl_loop_consumer.c \
100lib/ecore/efl_loop_fd.c \ 103lib/ecore/efl_loop_fd.c \
@@ -134,6 +137,8 @@ lib/ecore/efl_interpolator_spring.c \
134lib/ecore/efl_interpolator_cubic_bezier.c \ 137lib/ecore/efl_interpolator_cubic_bezier.c \
135lib/ecore/efl_task.c \ 138lib/ecore/efl_task.c \
136lib/ecore/efl_exe.c \ 139lib/ecore/efl_exe.c \
140lib/ecore/efl_thread.c \
141lib/ecore/efl_appthread.c \
137lib/ecore/ecore_main_timechanges.c \ 142lib/ecore/ecore_main_timechanges.c \
138lib/ecore/ecore_pipe.c \ 143lib/ecore/ecore_pipe.c \
139lib/ecore/ecore_poller.c \ 144lib/ecore/ecore_poller.c \
diff --git a/src/lib/ecore/Ecore_Eo.h b/src/lib/ecore/Ecore_Eo.h
index f5ce92d805..be4df7e377 100644
--- a/src/lib/ecore/Ecore_Eo.h
+++ b/src/lib/ecore/Ecore_Eo.h
@@ -45,9 +45,12 @@
45#include "efl_loop_message_handler.eo.h" 45#include "efl_loop_message_handler.eo.h"
46 46
47#include "efl_task.eo.h" 47#include "efl_task.eo.h"
48#include "efl_thread.eo.h"
48#include "efl_exe.eo.h" 49#include "efl_exe.eo.h"
49 50
50#include "efl_loop.eo.h" 51#include "efl_loop.eo.h"
52#include "efl_app.eo.h"
53#include "efl_appthread.eo.h"
51 54
52/** 55/**
53 * @brief Quits the main loop once all the events currently on the queue have 56 * @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
103 106
104/* We ue the factory pattern here, so you shouldn't call eo_add directly. */ 107/* We ue the factory pattern here, so you shouldn't call eo_add directly. */
105EAPI Eo *efl_main_loop_get(void); 108EAPI Eo *efl_main_loop_get(void);
109EAPI Eo *efl_app_get(void);
106 110
107typedef struct _Efl_Future_Composite_Progress Efl_Future_All_Progress; 111typedef struct _Efl_Future_Composite_Progress Efl_Future_All_Progress;
108 112
diff --git a/src/lib/ecore/ecore.c b/src/lib/ecore/ecore.c
index d911bc4e23..754b826314 100644
--- a/src/lib/ecore/ecore.c
+++ b/src/lib/ecore/ecore.c
@@ -215,8 +215,7 @@ _efl_first_loop_iterate(void *data, const Efl_Event *event)
215 case 'T': fprintf(stderr, "Loop started: '%f' - '%f' = '%f' sec\n", end, _efl_startup_time, end - _efl_startup_time); 215 case 'T': fprintf(stderr, "Loop started: '%f' - '%f' = '%f' sec\n", end, _efl_startup_time, end - _efl_startup_time);
216 break; 216 break;
217 } 217 }
218 218 efl_event_callback_del(event->object, EFL_APP_EVENT_RESUME,
219 efl_event_callback_del(event->object, EFL_LOOP_EVENT_RESUME,
220 _efl_first_loop_iterate, data); 219 _efl_first_loop_iterate, data);
221} 220}
222 221
@@ -345,13 +344,11 @@ ecore_init(void)
345 344
346 if (!_no_system_modules) 345 if (!_no_system_modules)
347 ecore_system_modules_load(); 346 ecore_system_modules_load();
348
349 if (getenv("EFL_FIRST_LOOP")) 347 if (getenv("EFL_FIRST_LOOP"))
350 efl_event_callback_add(efl_main_loop_get(), 348 efl_event_callback_add(efl_main_loop_get(),
351 EFL_LOOP_EVENT_RESUME, 349 EFL_APP_EVENT_RESUME,
352 _efl_first_loop_iterate, 350 _efl_first_loop_iterate,
353 getenv("EFL_FIRST_LOOP")); 351 getenv("EFL_FIRST_LOOP"));
354
355 _ecore_init_count_threshold = _ecore_init_count; 352 _ecore_init_count_threshold = _ecore_init_count;
356 353
357 eina_log_timing(_ecore_log_dom, 354 eina_log_timing(_ecore_log_dom,
@@ -390,8 +387,7 @@ ecore_shutdown(void)
390 } 387 }
391 if (_ecore_init_count-- != _ecore_init_count_threshold) 388 if (_ecore_init_count-- != _ecore_init_count_threshold)
392 goto end; 389 goto end;
393 390 efl_event_callback_call(efl_main_loop_get(), EFL_APP_EVENT_TERMINATE, NULL);
394 efl_event_callback_call(efl_main_loop_get(), EFL_LOOP_EVENT_TERMINATE, NULL);
395 391
396 ecore_system_modules_unload(); 392 ecore_system_modules_unload();
397 393
diff --git a/src/lib/ecore/ecore_exe.c b/src/lib/ecore/ecore_exe.c
index 908f677539..781dea60bd 100644
--- a/src/lib/ecore/ecore_exe.c
+++ b/src/lib/ecore/ecore_exe.c
@@ -66,7 +66,7 @@ ecore_exe_pipe_run(const char *exe_cmd,
66 const void *data) 66 const void *data)
67{ 67{
68 EINA_MAIN_LOOP_CHECK_RETURN_VAL(NULL); 68 EINA_MAIN_LOOP_CHECK_RETURN_VAL(NULL);
69 Ecore_Exe *ret = efl_add(MY_CLASS, efl_loop_main_get(EFL_LOOP_CLASS), 69 Ecore_Exe *ret = efl_add(MY_CLASS, efl_main_loop_get(),
70 ecore_obj_exe_command_set(efl_added, exe_cmd, 70 ecore_obj_exe_command_set(efl_added, exe_cmd,
71 flags)); 71 flags));
72 if (ret) 72 if (ret)
diff --git a/src/lib/ecore/ecore_main.c b/src/lib/ecore/ecore_main.c
index bc3c6c84a9..ebd572bb65 100644
--- a/src/lib/ecore/ecore_main.c
+++ b/src/lib/ecore/ecore_main.c
@@ -1372,7 +1372,7 @@ ecore_main_fd_handler_add(int fd,
1372{ 1372{
1373 Ecore_Fd_Handler *fdh = NULL; 1373 Ecore_Fd_Handler *fdh = NULL;
1374 EINA_MAIN_LOOP_CHECK_RETURN_VAL(NULL); 1374 EINA_MAIN_LOOP_CHECK_RETURN_VAL(NULL);
1375 fdh = _ecore_main_fd_handler_add(efl_loop_main_get(EFL_LOOP_CLASS), 1375 fdh = _ecore_main_fd_handler_add(efl_main_loop_get(),
1376 ML_DAT, NULL, fd, flags, func, data, 1376 ML_DAT, NULL, fd, flags, func, data,
1377 buf_func, buf_data, EINA_FALSE); 1377 buf_func, buf_data, EINA_FALSE);
1378 if (fdh) fdh->legacy = EINA_TRUE; 1378 if (fdh) fdh->legacy = EINA_TRUE;
@@ -1388,7 +1388,7 @@ ecore_main_fd_handler_file_add(int fd,
1388 const void *buf_data) 1388 const void *buf_data)
1389{ 1389{
1390 EINA_MAIN_LOOP_CHECK_RETURN_VAL(NULL); 1390 EINA_MAIN_LOOP_CHECK_RETURN_VAL(NULL);
1391 return _ecore_main_fd_handler_add(efl_loop_main_get(EFL_LOOP_CLASS), 1391 return _ecore_main_fd_handler_add(efl_main_loop_get(),
1392 ML_DAT, NULL, fd, flags, func, data, 1392 ML_DAT, NULL, fd, flags, func, data,
1393 buf_func, buf_data, EINA_TRUE); 1393 buf_func, buf_data, EINA_TRUE);
1394} 1394}
@@ -1595,7 +1595,7 @@ ecore_main_fd_handler_active_set(Ecore_Fd_Handler *fd_handler,
1595} 1595}
1596 1596
1597void 1597void
1598_ecore_main_content_clear(Efl_Loop_Data *pd) 1598_ecore_main_content_clear(Eo *obj, Efl_Loop_Data *pd)
1599{ 1599{
1600 Efl_Promise *promise; 1600 Efl_Promise *promise;
1601 Efl_Future *future; 1601 Efl_Future *future;
@@ -1608,7 +1608,7 @@ _ecore_main_content_clear(Efl_Loop_Data *pd)
1608 ecore_loop_promise_fulfill(promise); 1608 ecore_loop_promise_fulfill(promise);
1609 1609
1610 // FIXME 1610 // FIXME
1611 __eina_promise_cancel_all(); 1611 __eina_promise_cancel_data(obj);
1612 1612
1613 while (pd->fd_handlers) 1613 while (pd->fd_handlers)
1614 { 1614 {
diff --git a/src/lib/ecore/ecore_private.h b/src/lib/ecore/ecore_private.h
index 7ff80f57c3..7e44bf4acb 100644
--- a/src/lib/ecore/ecore_private.h
+++ b/src/lib/ecore/ecore_private.h
@@ -88,6 +88,7 @@ typedef struct _Efl_Loop_Future_Scheduler Efl_Loop_Future_Scheduler;
88typedef struct _Efl_Loop_Data Efl_Loop_Data; 88typedef struct _Efl_Loop_Data Efl_Loop_Data;
89 89
90typedef struct _Efl_Task_Data Efl_Task_Data; 90typedef struct _Efl_Task_Data Efl_Task_Data;
91typedef struct _Efl_Appthread_Data Efl_Appthread_Data;
91 92
92typedef struct _Message_Handler Message_Handler; 93typedef struct _Message_Handler Message_Handler;
93typedef struct _Message Message; 94typedef struct _Message Message;
@@ -193,6 +194,18 @@ struct _Efl_Task_Data
193 Eina_Bool exited : 1; 194 Eina_Bool exited : 1;
194}; 195};
195 196
197struct _Efl_Appthread_Data
198{
199 struct {
200 int in, out;
201 Eo *in_handler, *out_handler;
202 Eina_Bool can_read : 1;
203 Eina_Bool eos_read : 1;
204 Eina_Bool can_write : 1;
205 } fd, ctrl;
206 int read_listeners;
207};
208
196 209
197#define EVAS_FRAME_QUEUING 1 /* for test */ 210#define EVAS_FRAME_QUEUING 1 /* for test */
198 211
@@ -325,7 +338,7 @@ _ecore_main_win32_handler_del(Eo *obj,
325 Efl_Loop_Data *pd, 338 Efl_Loop_Data *pd,
326 Ecore_Win32_Handler *win32_handler); 339 Ecore_Win32_Handler *win32_handler);
327 340
328void _ecore_main_content_clear(Efl_Loop_Data *pd); 341void _ecore_main_content_clear(Eo *obj, Efl_Loop_Data *pd);
329void _ecore_main_shutdown(void); 342void _ecore_main_shutdown(void);
330 343
331#if defined (_WIN32) || defined (__lv2ppu__) || defined (HAVE_EXOTIC) 344#if defined (_WIN32) || defined (__lv2ppu__) || defined (HAVE_EXOTIC)
@@ -525,7 +538,7 @@ void ecore_loop_promise_fulfill(Efl_Promise *p);
525// access to direct input cb 538// access to direct input cb
526#define ECORE_EVAS_INTERNAL 539#define ECORE_EVAS_INTERNAL
527 540
528#define EFL_LOOP_DATA efl_data_scope_get(efl_loop_main_get(EFL_LOOP_CLASS), EFL_LOOP_CLASS) 541#define EFL_LOOP_DATA efl_data_scope_get(efl_main_loop_get(), EFL_LOOP_CLASS)
529 542
530EOAPI Eina_Bool efl_loop_message_process(Eo *obj); 543EOAPI Eina_Bool efl_loop_message_process(Eo *obj);
531 544
diff --git a/src/lib/ecore/ecore_signal.c b/src/lib/ecore/ecore_signal.c
index 98934e63b3..616f22b4ee 100644
--- a/src/lib/ecore/ecore_signal.c
+++ b/src/lib/ecore/ecore_signal.c
@@ -78,9 +78,9 @@ _ecore_signal_pipe_read(Eo *obj)
78 if (loop) 78 if (loop)
79 { 79 {
80 if (sdata.sig == SIGUSR1) 80 if (sdata.sig == SIGUSR1)
81 efl_event_callback_call(loop, EFL_LOOP_EVENT_SIGNAL_USR1, NULL); 81 efl_event_callback_call(loop, EFL_APP_EVENT_SIGNAL_USR1, NULL);
82 else 82 else
83 efl_event_callback_call(loop, EFL_LOOP_EVENT_SIGNAL_USR2, NULL); 83 efl_event_callback_call(loop, EFL_APP_EVENT_SIGNAL_USR2, NULL);
84 } 84 }
85 } 85 }
86 break; 86 break;
@@ -95,7 +95,7 @@ _ecore_signal_pipe_read(Eo *obj)
95 } 95 }
96 Eo *loop = efl_provider_find(obj, EFL_LOOP_CLASS); 96 Eo *loop = efl_provider_find(obj, EFL_LOOP_CLASS);
97 if (loop) 97 if (loop)
98 efl_event_callback_call(loop, EFL_LOOP_EVENT_SIGNAL_HUP, NULL); 98 efl_event_callback_call(loop, EFL_APP_EVENT_SIGNAL_HUP, NULL);
99 } 99 }
100 break; 100 break;
101 case SIGQUIT: 101 case SIGQUIT:
@@ -112,6 +112,9 @@ _ecore_signal_pipe_read(Eo *obj)
112 ecore_event_add(ECORE_EVENT_SIGNAL_EXIT, e, 112 ecore_event_add(ECORE_EVENT_SIGNAL_EXIT, e,
113 _ecore_signal_generic_free, NULL); 113 _ecore_signal_generic_free, NULL);
114 } 114 }
115 Eo *loop = efl_provider_find(obj, EFL_LOOP_CLASS);
116 if (loop)
117 efl_event_callback_call(loop, EFL_TASK_EVENT_EXIT, NULL);
115 } 118 }
116 break; 119 break;
117#ifdef SIGPWR 120#ifdef SIGPWR
diff --git a/src/lib/ecore/ecore_timer.c b/src/lib/ecore/ecore_timer.c
index 6ef4ab254c..7805f79de2 100644
--- a/src/lib/ecore/ecore_timer.c
+++ b/src/lib/ecore/ecore_timer.c
@@ -74,7 +74,7 @@ static void
74_check_timer_event_catcher_add(void *data, const Efl_Event *event) 74_check_timer_event_catcher_add(void *data, const Efl_Event *event)
75{ 75{
76 Efl_Loop_Timer_Data *timer = data; 76 Efl_Loop_Timer_Data *timer = data;
77 const Efl_Callback_Array_Item *array = event->info; 77 const Efl_Callback_Array_Item_Full *array = event->info;
78 int i; 78 int i;
79 79
80 for (i = 0; array[i].desc != NULL; i++) 80 for (i = 0; array[i].desc != NULL; i++)
@@ -94,7 +94,7 @@ static void
94_check_timer_event_catcher_del(void *data, const Efl_Event *event) 94_check_timer_event_catcher_del(void *data, const Efl_Event *event)
95{ 95{
96 Efl_Loop_Timer_Data *timer = data; 96 Efl_Loop_Timer_Data *timer = data;
97 const Efl_Callback_Array_Item *array = event->info; 97 const Efl_Callback_Array_Item_Full *array = event->info;
98 int i; 98 int i;
99 99
100 for (i = 0; array[i].desc != NULL; i++) 100 for (i = 0; array[i].desc != NULL; i++)
diff --git a/src/lib/ecore/efl_app.c b/src/lib/ecore/efl_app.c
new file mode 100644
index 0000000000..b6e2b1f29d
--- /dev/null
+++ b/src/lib/ecore/efl_app.c
@@ -0,0 +1,415 @@
1#ifdef HAVE_CONFIG_H
2# include <config.h>
3#endif
4
5#define EFL_IO_READER_PROTECTED 1
6#define EFL_IO_WRITER_PROTECTED 1
7#define EFL_IO_CLOSER_PROTECTED 1
8
9#include <Ecore.h>
10
11#include "ecore_private.h"
12
13#ifndef _WIN32
14# include <sys/resource.h>
15#endif
16
17#define MY_CLASS EFL_APP_CLASS
18
19typedef struct _Efl_App_Data Efl_App_Data;
20
21struct _Efl_App_Data
22{
23 struct {
24 int in, out;
25 Eo *in_handler, *out_handler;
26 Eina_Bool can_read : 1;
27 Eina_Bool eos_read : 1;
28 Eina_Bool can_write : 1;
29 } fd;
30 int read_listeners;
31};
32
33Efl_Version _app_efl_version = { 0, 0, 0, 0, NULL, NULL };
34
35//////////////////////////////////////////////////////////////////////////
36
37EAPI Eo *
38efl_app_get(void)
39{
40 return efl_main_loop_get();
41}
42
43//////////////////////////////////////////////////////////////////////////
44
45static void
46_parent_read_listeners_modify(Efl_App_Data *pd, int mod)
47{
48 pd->read_listeners += mod;
49
50 if (pd->fd.out_handler)
51 {
52 if ((pd->read_listeners == 0) && (mod < 0))
53 efl_loop_handler_active_set
54 (pd->fd.out_handler, EFL_LOOP_HANDLER_FLAGS_NONE);
55 else if ((pd->read_listeners == 1) && (mod > 0))
56 efl_loop_handler_active_set
57 (pd->fd.out_handler, EFL_LOOP_HANDLER_FLAGS_READ);
58 }
59}
60
61static void
62_cb_event_callback_add(void *data, const Efl_Event *event)
63{
64 Efl_App_Data *pd = data;
65 const Efl_Callback_Array_Item_Full *array = event->info;
66 int i;
67
68 for (i = 0; array[i].desc != NULL; i++)
69 {
70 if (array[i].desc == EFL_IO_READER_EVENT_CAN_READ_CHANGED)
71 _parent_read_listeners_modify(pd, 1);
72 }
73}
74
75static void
76_cb_event_callback_del(void *data, const Efl_Event *event)
77{
78 Efl_App_Data *pd = data;
79 const Efl_Callback_Array_Item_Full *array = event->info;
80 int i;
81
82 for (i = 0; array[i].desc != NULL; i++)
83 {
84 if (array[i].desc == EFL_IO_READER_EVENT_CAN_READ_CHANGED)
85 _parent_read_listeners_modify(pd, -1);
86 }
87}
88
89static void
90_cb_out(void *data, const Efl_Event *event EINA_UNUSED)
91{
92 Eo *obj = data;
93 efl_io_reader_can_read_set(obj, EINA_TRUE);
94}
95
96static void
97_cb_in(void *data, const Efl_Event *event EINA_UNUSED)
98{
99 Eo *obj = data;
100 efl_io_writer_can_write_set(obj, EINA_TRUE);
101}
102
103
104EFL_CALLBACKS_ARRAY_DEFINE(_event_callback_watch,
105 { EFL_EVENT_CALLBACK_ADD, _cb_event_callback_add },
106 { EFL_EVENT_CALLBACK_DEL, _cb_event_callback_del });
107
108//////////////////////////////////////////////////////////////////////////
109
110EOLIAN static Efl_Loop *
111_efl_app_loop_main_get(Eo *obj EINA_UNUSED, void *pd EINA_UNUSED)
112{
113 if (_mainloop_singleton) return _mainloop_singleton;
114 _mainloop_singleton = efl_add(EFL_APP_CLASS, NULL);
115 _mainloop_singleton_data = efl_data_scope_get(_mainloop_singleton, EFL_LOOP_CLASS);
116 return _mainloop_singleton;
117}
118
119EOLIAN static const Efl_Version *
120_efl_app_build_efl_version_get(Eo *obj EINA_UNUSED, Efl_App_Data *pd EINA_UNUSED)
121{
122 return &_app_efl_version;
123}
124
125EOLIAN static const Efl_Version *
126_efl_app_efl_version_get(Eo *obj EINA_UNUSED, Efl_App_Data *pd EINA_UNUSED)
127{
128 /* vanilla EFL: flavor = NULL */
129 static const Efl_Version version = {
130 .major = VMAJ,
131 .minor = VMIN,
132 .micro = VMIC,
133 .revision = VREV,
134 .build_id = EFL_BUILD_ID,
135 .flavor = NULL
136 };
137 return &version;
138}
139
140EOLIAN static Efl_Object *
141_efl_app_efl_object_constructor(Eo *obj, Efl_App_Data *pd)
142{
143 obj = efl_constructor(efl_super(obj, MY_CLASS));
144 efl_event_callback_array_add(obj, _event_callback_watch(), pd);
145 pd->fd.in = 1;
146 pd->fd.out = 0;
147 pd->fd.can_write = EINA_TRUE;
148 pd->fd.in_handler =
149 efl_add(EFL_LOOP_HANDLER_CLASS, obj,
150 efl_loop_handler_fd_set(efl_added, pd->fd.in),
151 efl_event_callback_add
152 (efl_added, EFL_LOOP_HANDLER_EVENT_WRITE, _cb_in, obj));
153 pd->fd.out_handler =
154 efl_add(EFL_LOOP_HANDLER_CLASS, obj,
155 efl_loop_handler_fd_set(efl_added, pd->fd.out),
156 efl_event_callback_add
157 (efl_added, EFL_LOOP_HANDLER_EVENT_READ, _cb_out, obj));
158 return obj;
159}
160
161EOLIAN static void
162_efl_app_efl_object_destructor(Eo *obj, Efl_App_Data *pd)
163{
164 efl_del(pd->fd.in_handler);
165 efl_del(pd->fd.out_handler);
166 pd->fd.in_handler = NULL;
167 pd->fd.out_handler = NULL;
168 pd->fd.in = -1;
169 pd->fd.out = -1;
170 efl_destructor(efl_super(obj, MY_CLASS));
171}
172
173EOLIAN static Eina_Error
174_efl_app_efl_io_closer_close(Eo *obj, Efl_App_Data *pd)
175{
176 EINA_SAFETY_ON_TRUE_RETURN_VAL(efl_io_closer_closed_get(obj), EBADF);
177 efl_io_writer_can_write_set(obj, EINA_FALSE);
178 efl_io_reader_can_read_set(obj, EINA_FALSE);
179 efl_io_reader_eos_set(obj, EINA_TRUE);
180 if (pd->fd.in_handler) efl_del(pd->fd.in_handler);
181 if (pd->fd.out_handler) efl_del(pd->fd.out_handler);
182 pd->fd.in = -1;
183 pd->fd.out = -1;
184 pd->fd.in_handler = NULL;
185 pd->fd.out_handler = NULL;
186 return 0;
187}
188
189EOLIAN static Eina_Bool
190_efl_app_efl_io_closer_closed_get(Eo *obj EINA_UNUSED, Efl_App_Data *pd)
191{
192 if ((pd->fd.in == -1) && (pd->fd.out == -1)) return EINA_TRUE;
193 return EINA_FALSE;
194}
195
196EOLIAN static Eina_Error
197_efl_app_efl_io_reader_read(Eo *obj, Efl_App_Data *pd, Eina_Rw_Slice *rw_slice)
198{
199 ssize_t r;
200
201 errno = 0;
202 if (pd->fd.out == -1) goto err;
203
204 do
205 {
206 errno = 0;
207 r = read(pd->fd.out, rw_slice->mem, rw_slice->len);
208 if (r == -1)
209 {
210 if (errno == EINTR) continue;
211 goto err;
212 }
213 }
214 while (r == -1);
215
216 rw_slice->len = r;
217 if (r == 0)
218 {
219 efl_io_reader_can_read_set(obj, EINA_FALSE);
220 efl_io_reader_eos_set(obj, EINA_TRUE);
221 close(pd->fd.out);
222 pd->fd.out = -1;
223 efl_del(pd->fd.out_handler);
224 pd->fd.out_handler = NULL;
225 return EPIPE;
226 }
227 return 0;
228err:
229 if ((pd->fd.out != -1) && (errno != EAGAIN))
230 {
231 close(pd->fd.out);
232 pd->fd.out = -1;
233 efl_del(pd->fd.out_handler);
234 pd->fd.out_handler = NULL;
235 }
236 rw_slice->len = 0;
237 rw_slice->mem = NULL;
238 efl_io_reader_can_read_set(obj, EINA_FALSE);
239 return EINVAL;
240}
241
242EOLIAN static void
243_efl_app_efl_io_reader_can_read_set(Eo *obj, Efl_App_Data *pd, Eina_Bool can_read)
244{
245 Eina_Bool old = efl_io_reader_can_read_get(obj);
246 if (old == can_read) return;
247 pd->fd.can_read = can_read;
248 if (can_read)
249 efl_loop_handler_active_set(pd->fd.in_handler, 0);
250 else
251 efl_loop_handler_active_set(pd->fd.in_handler,
252 EFL_LOOP_HANDLER_FLAGS_READ);
253 efl_event_callback_call(obj, EFL_IO_READER_EVENT_CAN_READ_CHANGED, NULL);
254}
255
256EOLIAN static Eina_Bool
257_efl_app_efl_io_reader_can_read_get(Eo *obj EINA_UNUSED, Efl_App_Data *pd)
258{
259 return pd->fd.can_read;
260}
261
262EOLIAN static void
263_efl_app_efl_io_reader_eos_set(Eo *obj, Efl_App_Data *pd, Eina_Bool is_eos)
264{
265 Eina_Bool old = efl_io_reader_eos_get(obj);
266 if (old == is_eos) return;
267
268 pd->fd.eos_read = is_eos;
269 if (!is_eos) return;
270 if (pd->fd.out_handler)
271 efl_loop_handler_active_set(pd->fd.out_handler, 0);
272 efl_event_callback_call(obj, EFL_IO_READER_EVENT_EOS, NULL);
273}
274
275EOLIAN static Eina_Bool
276_efl_app_efl_io_reader_eos_get(Eo *obj EINA_UNUSED, Efl_App_Data *pd)
277{
278 return pd->fd.eos_read;
279}
280
281EOLIAN static Eina_Error
282_efl_app_efl_io_writer_write(Eo *obj, Efl_App_Data *pd, Eina_Slice *slice, Eina_Slice *remaining)
283{
284 ssize_t r;
285
286 errno = 0;
287 if (pd->fd.in == -1) goto err;
288
289 do
290 {
291 errno = 0;
292 r = write(pd->fd.in, slice->mem, slice->len);
293 if (r == -1)
294 {
295 if (errno == EINTR) continue;
296 goto err;
297 }
298 }
299 while (r == -1);
300
301 if (remaining)
302 {
303 remaining->len = slice->len - r;
304 remaining->bytes = slice->bytes + r;
305 }
306 slice->len = r;
307
308 if ((slice) && (slice->len > 0))
309 efl_io_writer_can_write_set(obj, EINA_FALSE);
310 if (r == 0)
311 {
312 close(pd->fd.in);
313 pd->fd.in = -1;
314 efl_del(pd->fd.in_handler);
315 pd->fd.in_handler = NULL;
316 return EPIPE;
317 }
318 return 0;
319err:
320 if ((pd->fd.in != -1) && (errno != EAGAIN))
321 {
322 close(pd->fd.in);
323 pd->fd.in = -1;
324 efl_del(pd->fd.in_handler);
325 pd->fd.in_handler = NULL;
326 }
327 if (remaining) *remaining = *slice;
328 slice->len = 0;
329 slice->mem = NULL;
330 efl_io_writer_can_write_set(obj, EINA_FALSE);
331 return EINVAL;
332}
333
334EOLIAN static void
335_efl_app_efl_io_writer_can_write_set(Eo *obj, Efl_App_Data *pd, Eina_Bool can_write)
336{
337 Eina_Bool old = efl_io_writer_can_write_get(obj);
338 if (old == can_write) return;
339 pd->fd.can_write = can_write;
340 if (can_write)
341 efl_loop_handler_active_set(pd->fd.in_handler, 0);
342 else
343 efl_loop_handler_active_set(pd->fd.in_handler,
344 EFL_LOOP_HANDLER_FLAGS_WRITE);
345 efl_event_callback_call(obj, EFL_IO_WRITER_EVENT_CAN_WRITE_CHANGED, NULL);
346}
347
348EOLIAN static Eina_Bool
349_efl_app_efl_io_writer_can_write_get(Eo *obj EINA_UNUSED, Efl_App_Data *pd)
350{
351 return pd->fd.can_write;
352}
353
354#ifdef _WIN32
355#else
356static const signed char primap[EFL_TASK_PRIORITY_ULTRA + 1] =
357{
358 10, // EFL_TASK_PRIORITY_NORMAL
359 19, // EFL_TASK_PRIORITY_BACKGROUND
360 15, // EFL_TASK_PRIORITY_LOW
361 5, // EFL_TASK_PRIORITY_HIGH
362 0 // EFL_TASK_PRIORITY_ULTRA
363};
364#endif
365
366EOLIAN static void
367_efl_app_efl_task_priority_set(Eo *obj, Efl_App_Data *pd EINA_UNUSED, Efl_Task_Priority priority)
368{
369 efl_task_priority_set(efl_super(obj, MY_CLASS), priority);
370#ifdef _WIN32
371#else
372 // -20 (high) -> 19 (low)
373 int p = 0;
374
375 if ((priority >= EFL_TASK_PRIORITY_NORMAL) &&
376 (priority <= EFL_TASK_PRIORITY_ULTRA))
377 p = primap[priority];
378 setpriority(PRIO_PROCESS, 0, p);
379#endif
380}
381
382EOLIAN static Efl_Task_Priority
383_efl_app_efl_task_priority_get(Eo *obj, Efl_App_Data *pd EINA_UNUSED)
384{
385 Efl_Task_Priority pri = EFL_TASK_PRIORITY_NORMAL;
386#ifdef _WIN32
387#else
388 int p, i, dist = 0x7fffffff, d;
389
390 errno = 0;
391 p = getpriority(PRIO_PROCESS, 0);
392 if (errno != 0)
393 return efl_task_priority_get(efl_super(obj, MY_CLASS));
394
395 // find the closest matching priority in primap
396 for (i = EFL_TASK_PRIORITY_NORMAL; i <= EFL_TASK_PRIORITY_ULTRA; i++)
397 {
398 d = primap[i] - p;
399 if (d < 0) d = -d;
400 if (d < dist)
401 {
402 pri = i;
403 dist = d;
404 }
405 }
406
407 Efl_Task_Data *td = efl_data_scope_get(obj, EFL_TASK_CLASS);
408 if (td) td->priority = pri;
409#endif
410 return pri;
411}
412
413//////////////////////////////////////////////////////////////////////////
414
415#include "efl_app.eo.c"
diff --git a/src/lib/ecore/efl_app.eo b/src/lib/ecore/efl_app.eo
new file mode 100644
index 0000000000..97e08957e2
--- /dev/null
+++ b/src/lib/ecore/efl_app.eo
@@ -0,0 +1,57 @@
1import efl_types;
2import eina_types;
3
4class Efl.App (Efl.Loop)
5{
6 [[ ]]
7 methods {
8 @property loop_main @class {
9 [[ Points to the main loop instance of the application. ]]
10 get {}
11 values {
12 main_loop: Efl.Loop; [[Application main loop]]
13 }
14 }
15 @property build_efl_version {
16 [[ Indicates the version of EFL with which this application was
17 compiled against/for.
18
19 This might differ from @.efl_version.
20 ]]
21 get {}
22 values {
23 @cref version: Efl.Version; [[Efl version]]
24 }
25 }
26 @property efl_version {
27 [[ Indicates the currently running version of EFL.
28
29 This might differ from @.build_efl_version.
30 ]]
31 get {}
32 values {
33 @cref version: Efl.Version; [[Efl version]]
34 }
35 }
36 }
37 events {
38 pause; [[Called when the application is not going be displayed or otherwise used by a user for some time]]
39 resume; [[Called before a window is rendered after a pause event]]
40 terminate; [[Called before starting the shutdown of the application]]
41 signal,usr1; [[System specific, but on unix maps to SIGUSR1 signal to the process - only called on main loop object]]
42 signal,usr2; [[System specific, but on unix maps to SIGUSR2 signal to the process - only called on main loop object]]
43 signal,hup; [[System specific, but on unix maps to SIGHUP signal to the process - only called on main loop object]]
44 }
45 implements {
46 Efl.Object.constructor;
47 Efl.Object.destructor;
48 Efl.Io.Closer.close;
49 Efl.Io.Closer.closed { get; }
50 Efl.Io.Reader.read;
51 Efl.Io.Reader.can_read { get; set; }
52 Efl.Io.Reader.eos { get; set; }
53 Efl.Io.Writer.write;
54 Efl.Io.Writer.can_write { get; set; }
55 Efl.Task.priority { get; set; }
56 }
57}
diff --git a/src/lib/ecore/efl_appthread.c b/src/lib/ecore/efl_appthread.c
new file mode 100644
index 0000000000..93de9c0917
--- /dev/null
+++ b/src/lib/ecore/efl_appthread.c
@@ -0,0 +1,245 @@
1#ifdef HAVE_CONFIG_H
2# include <config.h>
3#endif
4
5#define EFL_IO_READER_PROTECTED 1
6#define EFL_IO_WRITER_PROTECTED 1
7#define EFL_IO_CLOSER_PROTECTED 1
8
9#include <Ecore.h>
10
11#include "ecore_private.h"
12
13#include <unistd.h>
14#include <fcntl.h>
15#include <string.h>
16
17#define MY_CLASS EFL_APPTHREAD_CLASS
18
19//////////////////////////////////////////////////////////////////////////
20
21//////////////////////////////////////////////////////////////////////////
22
23EOLIAN static Efl_Object *
24_efl_appthread_efl_object_constructor(Eo *obj, Efl_Appthread_Data *pd)
25{
26 obj = efl_constructor(efl_super(obj, MY_CLASS));
27 pd->fd.in = -1;
28 pd->fd.out = -1;
29 pd->fd.can_write = EINA_TRUE;
30 pd->ctrl.in = -1;
31 pd->ctrl.out = -1;
32 return obj;
33}
34
35EOLIAN static void
36_efl_appthread_efl_object_destructor(Eo *obj, Efl_Appthread_Data *pd)
37{
38 if (pd->fd.in >= 0)
39 {
40 efl_del(pd->fd.in_handler);
41 efl_del(pd->fd.out_handler);
42 efl_del(pd->ctrl.in_handler);
43 efl_del(pd->ctrl.out_handler);
44 close(pd->fd.in);
45 close(pd->fd.out);
46 close(pd->ctrl.in);
47 close(pd->ctrl.out);
48 pd->fd.in_handler = NULL;
49 pd->fd.out_handler = NULL;
50 pd->ctrl.in_handler = NULL;
51 pd->ctrl.out_handler = NULL;
52 pd->fd.in = -1;
53 pd->fd.out = -1;
54 pd->ctrl.in = -1;
55 pd->ctrl.out = -1;
56 }
57 efl_destructor(efl_super(obj, MY_CLASS));
58}
59
60EOLIAN static Eina_Error
61_efl_appthread_efl_io_closer_close(Eo *obj, Efl_Appthread_Data *pd)
62{
63 EINA_SAFETY_ON_TRUE_RETURN_VAL(efl_io_closer_closed_get(obj), EBADF);
64 efl_io_writer_can_write_set(obj, EINA_FALSE);
65 efl_io_reader_can_read_set(obj, EINA_FALSE);
66 efl_io_reader_eos_set(obj, EINA_TRUE);
67 if (pd->fd.in >= 0) close(pd->fd.in);
68 if (pd->fd.out >= 0) close(pd->fd.out);
69 if (pd->fd.in_handler) efl_del(pd->fd.in_handler);
70 if (pd->fd.out_handler) efl_del(pd->fd.out_handler);
71 pd->fd.in = -1;
72 pd->fd.out = -1;
73 pd->fd.in_handler = NULL;
74 pd->fd.out_handler = NULL;
75 return 0;
76}
77
78EOLIAN static Eina_Bool
79_efl_appthread_efl_io_closer_closed_get(Eo *obj EINA_UNUSED, Efl_Appthread_Data *pd)
80{
81 if ((pd->fd.in == -1) && (pd->fd.out == -1)) return EINA_TRUE;
82 return EINA_FALSE;
83}
84
85EOLIAN static Eina_Error
86_efl_appthread_efl_io_reader_read(Eo *obj, Efl_Appthread_Data *pd, Eina_Rw_Slice *rw_slice)
87{
88 ssize_t r;
89
90 errno = 0;
91 if (pd->fd.out == -1) goto err;
92
93 do
94 {
95 errno = 0;
96 r = read(pd->fd.out, rw_slice->mem, rw_slice->len);
97 if (r == -1)
98 {
99 if (errno == EINTR) continue;
100 goto err;
101 }
102 }
103 while (r == -1);
104
105 rw_slice->len = r;
106 if (r == 0)
107 {
108 efl_io_reader_can_read_set(obj, EINA_FALSE);
109 efl_io_reader_eos_set(obj, EINA_TRUE);
110 close(pd->fd.out);
111 pd->fd.out = -1;
112 efl_del(pd->fd.out_handler);
113 pd->fd.out_handler = NULL;
114 return EPIPE;
115 }
116 return 0;
117err:
118 if ((pd->fd.out != -1) && (errno != EAGAIN))
119 {
120 close(pd->fd.out);
121 pd->fd.out = -1;
122 efl_del(pd->fd.out_handler);
123 pd->fd.out_handler = NULL;
124 }
125 rw_slice->len = 0;
126 rw_slice->mem = NULL;
127 efl_io_reader_can_read_set(obj, EINA_FALSE);
128 return EINVAL;
129}
130
131EOLIAN static void
132_efl_appthread_efl_io_reader_can_read_set(Eo *obj, Efl_Appthread_Data *pd, Eina_Bool can_read)
133{
134 Eina_Bool old = efl_io_reader_can_read_get(obj);
135 if (old == can_read) return;
136 pd->fd.can_read = can_read;
137 if (can_read)
138 efl_loop_handler_active_set(pd->fd.in_handler, 0);
139 else
140 efl_loop_handler_active_set(pd->fd.in_handler,
141 EFL_LOOP_HANDLER_FLAGS_READ);
142 efl_event_callback_call(obj, EFL_IO_READER_EVENT_CAN_READ_CHANGED, NULL);
143}
144
145EOLIAN static Eina_Bool
146_efl_appthread_efl_io_reader_can_read_get(Eo *obj EINA_UNUSED, Efl_Appthread_Data *pd)
147{
148 return pd->fd.can_read;
149}
150
151EOLIAN static void
152_efl_appthread_efl_io_reader_eos_set(Eo *obj, Efl_Appthread_Data *pd, Eina_Bool is_eos)
153{
154 Eina_Bool old = efl_io_reader_eos_get(obj);
155 if (old == is_eos) return;
156
157 pd->fd.eos_read = is_eos;
158 if (!is_eos) return;
159 if (pd->fd.out_handler)
160 efl_loop_handler_active_set(pd->fd.out_handler, 0);
161 efl_event_callback_call(obj, EFL_IO_READER_EVENT_EOS, NULL);
162}
163
164EOLIAN static Eina_Bool
165_efl_appthread_efl_io_reader_eos_get(Eo *obj EINA_UNUSED, Efl_Appthread_Data *pd)
166{
167 return pd->fd.eos_read;
168}
169
170EOLIAN static Eina_Error
171_efl_appthread_efl_io_writer_write(Eo *obj, Efl_Appthread_Data *pd, Eina_Slice *slice, Eina_Slice *remaining)
172{
173 ssize_t r;
174
175 errno = 0;
176 if (pd->fd.in == -1) goto err;
177
178 do
179 {
180 errno = 0;
181 r = write(pd->fd.in, slice->mem, slice->len);
182 if (r == -1)
183 {
184 if (errno == EINTR) continue;
185 goto err;
186 }
187 }
188 while (r == -1);
189
190 if (remaining)
191 {
192 remaining->len = slice->len - r;
193 remaining->bytes = slice->bytes + r;
194 }
195 slice->len = r;
196
197 if ((slice) && (slice->len > 0))
198 efl_io_writer_can_write_set(obj, EINA_FALSE);
199 if (r == 0)
200 {
201 close(pd->fd.in);
202 pd->fd.in = -1;
203 efl_del(pd->fd.in_handler);
204 pd->fd.in_handler = NULL;
205 return EPIPE;
206 }
207 return 0;
208err:
209 if ((pd->fd.in != -1) && (errno != EAGAIN))
210 {
211 close(pd->fd.in);
212 pd->fd.in = -1;
213 efl_del(pd->fd.in_handler);
214 pd->fd.in_handler = NULL;
215 }
216 if (remaining) *remaining = *slice;
217 slice->len = 0;
218 slice->mem = NULL;
219 efl_io_writer_can_write_set(obj, EINA_FALSE);
220 return EINVAL;
221}
222
223EOLIAN static void
224_efl_appthread_efl_io_writer_can_write_set(Eo *obj, Efl_Appthread_Data *pd, Eina_Bool can_write)
225{
226 Eina_Bool old = efl_io_writer_can_write_get(obj);
227 if (old == can_write) return;
228 pd->fd.can_write = can_write;
229 if (can_write)
230 efl_loop_handler_active_set(pd->fd.in_handler, 0);
231 else
232 efl_loop_handler_active_set(pd->fd.in_handler,
233 EFL_LOOP_HANDLER_FLAGS_WRITE);
234 efl_event_callback_call(obj, EFL_IO_WRITER_EVENT_CAN_WRITE_CHANGED, NULL);
235}
236
237EOLIAN static Eina_Bool
238_efl_appthread_efl_io_writer_can_write_get(Eo *obj EINA_UNUSED, Efl_Appthread_Data *pd)
239{
240 return pd->fd.can_write;
241}
242
243//////////////////////////////////////////////////////////////////////////
244
245#include "efl_appthread.eo.c"
diff --git a/src/lib/ecore/efl_appthread.eo b/src/lib/ecore/efl_appthread.eo
new file mode 100644
index 0000000000..2f5021a720
--- /dev/null
+++ b/src/lib/ecore/efl_appthread.eo
@@ -0,0 +1,22 @@
1import efl_types;
2import eina_types;
3
4class Efl.Appthread (Efl.Loop)
5{
6 [[ ]]
7 methods {
8 }
9 events {
10 }
11 implements {
12 Efl.Object.constructor;
13 Efl.Object.destructor;
14 Efl.Io.Closer.close;
15 Efl.Io.Closer.closed { get; }
16 Efl.Io.Reader.read;
17 Efl.Io.Reader.can_read { get; set; }
18 Efl.Io.Reader.eos { get; set; }
19 Efl.Io.Writer.write;
20 Efl.Io.Writer.can_write { get; set; }
21 }
22}
diff --git a/src/lib/ecore/efl_exe.c b/src/lib/ecore/efl_exe.c
index ed9c53c583..1443bbf071 100644
--- a/src/lib/ecore/efl_exe.c
+++ b/src/lib/ecore/efl_exe.c
@@ -179,15 +179,30 @@ _foreach_env(const Eina_Hash *hash EINA_UNUSED, const void *key, void *data, voi
179 return EINA_TRUE; 179 return EINA_TRUE;
180} 180}
181 181
182static Eina_Value
183_efl_loop_task_exit(void *data, const Eina_Value v,
184 const Eina_Future *dead EINA_UNUSED)
185{
186 Eo *obj = data;
187
188 efl_event_callback_call(obj, EFL_TASK_EVENT_EXIT, NULL);
189 efl_unref(obj);
190 return v;
191}
192
182static void 193static void
183_exe_exit_eval(Eo *obj, Efl_Exe_Data *pd) 194_exe_exit_eval(Eo *obj, Efl_Exe_Data *pd)
184{ 195{
185 // XXX: defer the below in a job 196 if ((pd->fd.out == -1) && /*(pd->fd.in == -1) &&*/
186 if ((pd->fd.out == -1) && (pd->fd.exited_read == -1) && 197 (pd->fd.exited_read == -1) && (!pd->exit_called))
187 (!pd->exit_called))
188 { 198 {
199 Eina_Future *job;
200 Eo *loop = efl_provider_find(obj, EFL_LOOP_CLASS);
201
189 pd->exit_called = EINA_TRUE; 202 pd->exit_called = EINA_TRUE;
190 efl_event_callback_call(obj, EFL_TASK_EVENT_EXIT, NULL); 203 efl_ref(obj);
204 job = eina_future_then(efl_loop_job(loop), _efl_loop_task_exit, obj);
205 efl_future_Eina_FutureXXX_then(loop, job);
191 } 206 }
192} 207}
193 208
@@ -666,10 +681,11 @@ _efl_exe_efl_io_reader_can_read_set(Eo *obj, Efl_Exe_Data *pd, Eina_Bool can_rea
666 Eina_Bool old = efl_io_reader_can_read_get(obj); 681 Eina_Bool old = efl_io_reader_can_read_get(obj);
667 if (old == can_read) return; 682 if (old == can_read) return;
668 pd->fd.can_read = can_read; 683 pd->fd.can_read = can_read;
684 if (!pd->fd.out_handler) return;
669 if (can_read) 685 if (can_read)
670 efl_loop_handler_active_set(pd->fd.in_handler, 0); 686 efl_loop_handler_active_set(pd->fd.out_handler, 0);
671 else 687 else
672 efl_loop_handler_active_set(pd->fd.in_handler, 688 efl_loop_handler_active_set(pd->fd.out_handler,
673 EFL_LOOP_HANDLER_FLAGS_READ); 689 EFL_LOOP_HANDLER_FLAGS_READ);
674 efl_event_callback_call(obj, EFL_IO_READER_EVENT_CAN_READ_CHANGED, NULL); 690 efl_event_callback_call(obj, EFL_IO_READER_EVENT_CAN_READ_CHANGED, NULL);
675} 691}
diff --git a/src/lib/ecore/efl_general.h b/src/lib/ecore/efl_general.h
index 256f1065a4..222c799c2c 100644
--- a/src/lib/ecore/efl_general.h
+++ b/src/lib/ecore/efl_general.h
@@ -107,9 +107,9 @@
107#define EFL_MAIN_EX() \ 107#define EFL_MAIN_EX() \
108 EFL_CALLBACKS_ARRAY_DEFINE(_efl_main_ex, \ 108 EFL_CALLBACKS_ARRAY_DEFINE(_efl_main_ex, \
109 { EFL_LOOP_EVENT_ARGUMENTS, efl_main }, \ 109 { EFL_LOOP_EVENT_ARGUMENTS, efl_main }, \
110 { EFL_LOOP_EVENT_PAUSE, efl_pause }, \ 110 { EFL_APP_EVENT_PAUSE, efl_pause }, \
111 { EFL_LOOP_EVENT_RESUME, efl_resume }, \ 111 { EFL_APP_EVENT_RESUME, efl_resume }, \
112 { EFL_LOOP_EVENT_TERMINATE, efl_terminate }); \ 112 { EFL_APP_EVENT_TERMINATE, efl_terminate }); \
113 int main(int argc, char **argv) \ 113 int main(int argc, char **argv) \
114 { \ 114 { \
115 Eina_Value *ret__; \ 115 Eina_Value *ret__; \
diff --git a/src/lib/ecore/efl_loop.c b/src/lib/ecore/efl_loop.c
index 74a12deb50..0ccee1706f 100644
--- a/src/lib/ecore/efl_loop.c
+++ b/src/lib/ecore/efl_loop.c
@@ -8,9 +8,6 @@
8#include <unistd.h> 8#include <unistd.h>
9#include <math.h> 9#include <math.h>
10#include <sys/time.h> 10#include <sys/time.h>
11#ifndef _WIN32
12# include <sys/resource.h>
13#endif
14#include <errno.h> 11#include <errno.h>
15 12
16#include "Ecore.h" 13#include "Ecore.h"
@@ -53,8 +50,6 @@ _efl_loop_message_handler_get(Eo *obj EINA_UNUSED, void *pd EINA_UNUSED, Efl_Loo
53 return mh.handler; 50 return mh.handler;
54} 51}
55 52
56Efl_Version _app_efl_version = { 0, 0, 0, 0, NULL, NULL };
57
58Eo *_mainloop_singleton = NULL; 53Eo *_mainloop_singleton = NULL;
59Efl_Loop_Data *_mainloop_singleton_data = NULL; 54Efl_Loop_Data *_mainloop_singleton_data = NULL;
60 55
@@ -63,19 +58,10 @@ static Eina_List *_environ_strings_set = NULL;
63 58
64static void _clean_old_environ(void); 59static void _clean_old_environ(void);
65 60
66EOLIAN static Efl_Loop *
67_efl_loop_main_get(Efl_Class *klass EINA_UNUSED, void *_pd EINA_UNUSED)
68{
69 if (_mainloop_singleton) return _mainloop_singleton;
70 _mainloop_singleton = efl_add(EFL_LOOP_CLASS, NULL);
71 _mainloop_singleton_data = efl_data_scope_get(_mainloop_singleton, EFL_LOOP_CLASS);
72 return _mainloop_singleton;
73}
74
75EAPI Eo * 61EAPI Eo *
76efl_main_loop_get(void) 62efl_main_loop_get(void)
77{ 63{
78 return efl_loop_main_get(EFL_LOOP_CLASS); 64 return efl_app_loop_main_get(EFL_APP_CLASS);
79} 65}
80 66
81EOLIAN static void 67EOLIAN static void
@@ -172,8 +158,8 @@ efl_loop_exit_code_process(Eina_Value *value)
172 Eina_Value v = EINA_VALUE_EMPTY; 158 Eina_Value v = EINA_VALUE_EMPTY;
173 159
174 eina_value_setup(&v, EINA_VALUE_TYPE_INT); 160 eina_value_setup(&v, EINA_VALUE_TYPE_INT);
175 if (!eina_value_convert(&v, value)) r = -1; 161 if (!eina_value_convert(value, &v)) r = -1;
176 else eina_value_get(&v, &v); 162 else eina_value_get(&v, &r);
177 } 163 }
178 else 164 else
179 { 165 {
@@ -203,7 +189,7 @@ _poll_trigger(void *data, const Efl_Event *event)
203static void 189static void
204_check_event_catcher_add(void *data, const Efl_Event *event) 190_check_event_catcher_add(void *data, const Efl_Event *event)
205{ 191{
206 const Efl_Callback_Array_Item *array = event->info; 192 const Efl_Callback_Array_Item_Full *array = event->info;
207 Efl_Loop_Data *pd = data; 193 Efl_Loop_Data *pd = data;
208 int i; 194 int i;
209 195
@@ -272,7 +258,7 @@ _check_event_catcher_add(void *data, const Efl_Event *event)
272static void 258static void
273_check_event_catcher_del(void *data, const Efl_Event *event) 259_check_event_catcher_del(void *data, const Efl_Event *event)
274{ 260{
275 const Efl_Callback_Array_Item *array = event->info; 261 const Efl_Callback_Array_Item_Full *array = event->info;
276 Efl_Loop_Data *pd = data; 262 Efl_Loop_Data *pd = data;
277 int i; 263 int i;
278 264
@@ -337,7 +323,7 @@ _efl_loop_efl_object_constructor(Eo *obj, Efl_Loop_Data *pd)
337EOLIAN static void 323EOLIAN static void
338_efl_loop_efl_object_destructor(Eo *obj, Efl_Loop_Data *pd) 324_efl_loop_efl_object_destructor(Eo *obj, Efl_Loop_Data *pd)
339{ 325{
340 _ecore_main_content_clear(pd); 326 _ecore_main_content_clear(obj, pd);
341 327
342 pd->future_message_handler = NULL; 328 pd->future_message_handler = NULL;
343 329
@@ -725,6 +711,7 @@ efl_build_version_set(int vmaj, int vmin, int vmic, int revision,
725 _app_efl_version.build_id = build_id ? strdup(build_id) : NULL; 711 _app_efl_version.build_id = build_id ? strdup(build_id) : NULL;
726} 712}
727 713
714/* HHH:
728EOLIAN static const Efl_Version * 715EOLIAN static const Efl_Version *
729_efl_loop_app_efl_version_get(Eo *obj EINA_UNUSED, Efl_Loop_Data *pd EINA_UNUSED) 716_efl_loop_app_efl_version_get(Eo *obj EINA_UNUSED, Efl_Loop_Data *pd EINA_UNUSED)
730{ 717{
@@ -734,7 +721,7 @@ _efl_loop_app_efl_version_get(Eo *obj EINA_UNUSED, Efl_Loop_Data *pd EINA_UNUSED
734EOLIAN static const Efl_Version * 721EOLIAN static const Efl_Version *
735_efl_loop_efl_version_get(Eo *obj EINA_UNUSED, Efl_Loop_Data *pd EINA_UNUSED) 722_efl_loop_efl_version_get(Eo *obj EINA_UNUSED, Efl_Loop_Data *pd EINA_UNUSED)
736{ 723{
737 /* vanilla EFL: flavor = NULL */ 724 // vanilla EFL: flavor = NULL
738 static const Efl_Version version = { 725 static const Efl_Version version = {
739 .major = VMAJ, 726 .major = VMAJ,
740 .minor = VMIN, 727 .minor = VMIN,
@@ -745,6 +732,7 @@ _efl_loop_efl_version_get(Eo *obj EINA_UNUSED, Efl_Loop_Data *pd EINA_UNUSED)
745 }; 732 };
746 return &version; 733 return &version;
747} 734}
735*/
748 736
749static void 737static void
750_env_sync(Efl_Loop_Data *pd, Efl_Task_Data *td) 738_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)
903 eina_lock_release(&_environ_lock); 891 eina_lock_release(&_environ_lock);
904 return efl_task_env_get(efl_super(obj, EFL_LOOP_CLASS), var); 892 return efl_task_env_get(efl_super(obj, EFL_LOOP_CLASS), var);
905} 893}
906#ifdef _WIN32 894
907#else 895EOLIAN static Eina_Bool
908static const signed char primap[EFL_TASK_PRIORITY_ULTRA + 1] = 896_efl_loop_efl_task_run(Eo *obj, Efl_Loop_Data *pd EINA_UNUSED)
909{ 897{
910 10, // EFL_TASK_PRIORITY_NORMAL 898 Eina_Value *ret;
911 19, // EFL_TASK_PRIORITY_BACKGROUND 899 int real;
912 15, // EFL_TASK_PRIORITY_LOW
913 5, // EFL_TASK_PRIORITY_HIGH
914 0 // EFL_TASK_PRIORITY_ULTRA
915};
916#endif
917 900
918EOLIAN static void 901 ret = efl_loop_begin(obj);
919_efl_loop_efl_task_priority_set(Eo *obj, Efl_Loop_Data *pd EINA_UNUSED, Efl_Task_Priority priority) 902 real = efl_loop_exit_code_process(ret);
920{ 903 if (real == 0) return EINA_TRUE;
921 efl_task_priority_set(efl_super(obj, EFL_LOOP_CLASS), priority); 904 return EINA_FALSE;
922#ifdef _WIN32
923#else
924 // -20 (high) -> 19 (low)
925 int p = 0;
926
927 if ((priority >= EFL_TASK_PRIORITY_NORMAL) &&
928 (priority <= EFL_TASK_PRIORITY_ULTRA))
929 p = primap[priority];
930 setpriority(PRIO_PROCESS, 0, p);
931#endif
932} 905}
933 906
934EOLIAN static Efl_Task_Priority 907EOLIAN static void
935_efl_loop_efl_task_priority_get(Eo *obj EINA_UNUSED, Efl_Loop_Data *pd EINA_UNUSED) 908_efl_loop_efl_task_end(Eo *obj, Efl_Loop_Data *pd EINA_UNUSED)
936{ 909{
937 Efl_Task_Priority pri = EFL_TASK_PRIORITY_NORMAL; 910 efl_loop_quit(obj, eina_value_int_init(0));
938#ifdef _WIN32
939#else
940 int p, i, dist = 0x7fffffff, d;
941
942 errno = 0;
943 p = getpriority(PRIO_PROCESS, 0);
944 if (errno != 0)
945 return efl_task_priority_get(efl_super(obj, EFL_LOOP_CLASS));
946
947 // find the closest matching priority in primap
948 for (i = EFL_TASK_PRIORITY_NORMAL; i <= EFL_TASK_PRIORITY_ULTRA; i++)
949 {
950 d = primap[i] - p;
951 if (d < 0) d = -d;
952 if (d < dist)
953 {
954 pri = i;
955 dist = d;
956 }
957 }
958
959 Efl_Task_Data *td = efl_data_scope_get(obj, EFL_TASK_CLASS);
960 if (td) td->priority = pri;
961#endif
962 return pri;
963} 911}
964 912
965EAPI Eina_Future_Scheduler * 913EAPI Eina_Future_Scheduler *
diff --git a/src/lib/ecore/efl_loop.eo b/src/lib/ecore/efl_loop.eo
index e6c1229772..1ecdd68538 100644
--- a/src/lib/ecore/efl_loop.eo
+++ b/src/lib/ecore/efl_loop.eo
@@ -20,33 +20,6 @@ class Efl.Loop (Efl.Task)
20 you can provide these if you need to. 20 you can provide these if you need to.
21 ]] 21 ]]
22 methods { 22 methods {
23 @property main @class {
24 [[Points to the main loop instance of the application.]]
25 get {}
26 values {
27 main_loop: Efl.Loop; [[Application main loop]]
28 }
29 }
30 @property app_efl_version {
31 [[Indicates the version of EFL with which this application was compiled.
32
33 This might differ from @.efl_version.
34 ]]
35 get {}
36 values {
37 @cref version: Efl.Version; [[Efl version]]
38 }
39 }
40 @property efl_version {
41 [[Indicates the currently running version of EFL.
42
43 This might differ from @.app_efl_version.
44 ]]
45 get {}
46 values {
47 @cref version: Efl.Version; [[Efl version]]
48 }
49 }
50 iterate { 23 iterate {
51 [[Runs a single iteration of the main loop to process everything on the 24 [[Runs a single iteration of the main loop to process everything on the
52 queue.]] 25 queue.]]
@@ -148,18 +121,13 @@ class Efl.Loop (Efl.Task)
148 poll,high; [[Event occurs multiple times per second. The exact tick is undefined and can be adjusted system wide.]] 121 poll,high; [[Event occurs multiple times per second. The exact tick is undefined and can be adjusted system wide.]]
149 poll,medium; [[Event occurs multiple times per minute. The exact tick is undefined and can be adjusted system wide.]] 122 poll,medium; [[Event occurs multiple times per minute. The exact tick is undefined and can be adjusted system wide.]]
150 poll,low; [[Event occurs multiple times every 15 minutes. The exact tick is undefined and can be adjusted system wide.]] 123 poll,low; [[Event occurs multiple times every 15 minutes. The exact tick is undefined and can be adjusted system wide.]]
151 pause; [[Called when the window is not going be displayed for some time]]
152 resume; [[Called before a window is rendered after a pause event]]
153 terminate; [[Called before starting the shutdown of Elementary]]
154 signal,usr1; [[System specific, but on unix maps to SIGUSR1 signal to the process - only called on main loop object]]
155 signal,usr2; [[System specific, but on unix maps to SIGUSR2 signal to the process - only called on main loop object]]
156 signal,hup; [[System specific, but on unix maps to SIGHUP signal to the process - only called on main loop object]]
157 } 124 }
158 implements { 125 implements {
159 Efl.Object.constructor; 126 Efl.Object.constructor;
160 Efl.Object.destructor; 127 Efl.Object.destructor;
161 Efl.Object.provider_find; 128 Efl.Object.provider_find;
162 Efl.Task.env { set; get; } 129 Efl.Task.env { set; get; }
163 Efl.Task.priority { get; set; } 130 Efl.Task.run;
131 Efl.Task.end;
164 } 132 }
165} 133}
diff --git a/src/lib/ecore/efl_loop_fd.c b/src/lib/ecore/efl_loop_fd.c
index 87cb58c41a..e6ec21d7b9 100644
--- a/src/lib/ecore/efl_loop_fd.c
+++ b/src/lib/ecore/efl_loop_fd.c
@@ -111,7 +111,7 @@ _efl_loop_fd_fd_file_get(Eo *obj EINA_UNUSED, Efl_Loop_Fd_Data *pd)
111static void 111static void
112_check_fd_event_catcher_add(void *data, const Efl_Event *event) 112_check_fd_event_catcher_add(void *data, const Efl_Event *event)
113{ 113{
114 const Efl_Callback_Array_Item *array = event->info; 114 const Efl_Callback_Array_Item_Full *array = event->info;
115 Efl_Loop_Fd_Data *fd = data; 115 Efl_Loop_Fd_Data *fd = data;
116 Eina_Bool need_reset = EINA_FALSE; 116 Eina_Bool need_reset = EINA_FALSE;
117 int i; 117 int i;
@@ -142,7 +142,7 @@ _check_fd_event_catcher_add(void *data, const Efl_Event *event)
142static void 142static void
143_check_fd_event_catcher_del(void *data, const Efl_Event *event) 143_check_fd_event_catcher_del(void *data, const Efl_Event *event)
144{ 144{
145 const Efl_Callback_Array_Item *array = event->info; 145 const Efl_Callback_Array_Item_Full *array = event->info;
146 Efl_Loop_Fd_Data *fd = data; 146 Efl_Loop_Fd_Data *fd = data;
147 Eina_Bool need_reset = EINA_FALSE; 147 Eina_Bool need_reset = EINA_FALSE;
148 int i; 148 int i;
diff --git a/src/lib/ecore/efl_loop_handler.c b/src/lib/ecore/efl_loop_handler.c
index 39d05359dd..34e03a9cc4 100644
--- a/src/lib/ecore/efl_loop_handler.c
+++ b/src/lib/ecore/efl_loop_handler.c
@@ -132,7 +132,7 @@ _handler_reset(Eo *obj, Efl_Loop_Handler_Data *pd)
132static Eina_Bool 132static Eina_Bool
133_event_references_update(Efl_Loop_Handler_Data *pd, const Efl_Event *event, int increment) 133_event_references_update(Efl_Loop_Handler_Data *pd, const Efl_Event *event, int increment)
134{ 134{
135 const Efl_Callback_Array_Item *array = event->info; 135 const Efl_Callback_Array_Item_Full *array = event->info;
136 int i; 136 int i;
137 Eina_Bool need_reset = EINA_FALSE; 137 Eina_Bool need_reset = EINA_FALSE;
138 138
diff --git a/src/lib/ecore/efl_task.c b/src/lib/ecore/efl_task.c
index 18927e843e..9a727743ed 100644
--- a/src/lib/ecore/efl_task.c
+++ b/src/lib/ecore/efl_task.c
@@ -186,8 +186,8 @@ _escape(const char *s)
186 { 186 {
187 *d = '\"'; 187 *d = '\"';
188 d++; 188 d++;
189 *d = 0;
190 } 189 }
190 *d = 0;
191 return s2; 191 return s2;
192} 192}
193 193
@@ -215,7 +215,7 @@ _rebuild_command(Efl_Task_Data *pd)
215 char *str = _escape(arg); 215 char *str = _escape(arg);
216 if (str) 216 if (str)
217 { 217 {
218 if (!have_args) eina_strbuf_append(sb, " "); 218 if (have_args) eina_strbuf_append(sb, " ");
219 eina_strbuf_append(sb, str); 219 eina_strbuf_append(sb, str);
220 free(str); 220 free(str);
221 have_args = EINA_TRUE; 221 have_args = EINA_TRUE;
@@ -272,14 +272,17 @@ _efl_task_arg_value_set(Eo *obj EINA_UNUSED, Efl_Task_Data *pd, unsigned int num
272 272
273 if (!pd->args) pd->args = eina_array_new(16); 273 if (!pd->args) pd->args = eina_array_new(16);
274 count = eina_array_count(pd->args); 274 count = eina_array_count(pd->args);
275 if (count > num) 275 if ((count > 0) && (count > num))
276 parg = eina_array_data_get(pd->args, num); 276 parg = eina_array_data_get(pd->args, num);
277 else 277 else
278 { 278 {
279 unsigned int i; 279 unsigned int i;
280 280
281 for (i = count; i <= num; i++) 281 for (i = count; i <= num; i++)
282 eina_array_push(pd->args, NULL); 282 {
283 eina_array_push(pd->args, "");
284 eina_array_data_set(pd->args, i, NULL);
285 }
283 } 286 }
284 287
285 if (arg) 288 if (arg)
diff --git a/src/lib/ecore/efl_thread.c b/src/lib/ecore/efl_thread.c
new file mode 100644
index 0000000000..ffd4f4756f
--- /dev/null
+++ b/src/lib/ecore/efl_thread.c
@@ -0,0 +1,917 @@
1#ifdef HAVE_CONFIG_H
2# include <config.h>
3#endif
4
5#define EFL_IO_READER_PROTECTED 1
6#define EFL_IO_WRITER_PROTECTED 1
7#define EFL_IO_CLOSER_PROTECTED 1
8
9#include <Ecore.h>
10
11#include "ecore_private.h"
12
13#include <unistd.h>
14#include <fcntl.h>
15#include <string.h>
16
17#define MY_CLASS EFL_THREAD_CLASS
18
19typedef struct
20{
21 const char *name;
22 struct {
23 int in, out;
24 Eo *in_handler, *out_handler;
25 } fd, ctrl;
26 struct {
27 unsigned int argc;
28 const char **argv;
29 } args;
30 Efl_Callback_Array_Item_Full *event_cb;
31} Thread_Data;
32
33#define CMD_EXIT 1
34#define CMD_EXITED 2
35
36typedef struct
37{
38 int command;
39 int data;
40} Control_Data;
41
42typedef struct _Efl_Thread_Data Efl_Thread_Data;
43
44struct _Efl_Thread_Data
45{
46 struct {
47 int in, out;
48 Eo *in_handler, *out_handler;
49 Eina_Bool can_read : 1;
50 Eina_Bool eos_read : 1;
51 Eina_Bool can_write : 1;
52 } fd, ctrl;
53 int read_listeners;
54 Eo *loop;
55 Thread_Data *thdat;
56 Efl_Callback_Array_Item_Full *event_cb;
57 Eina_Thread thread;
58 Eina_Bool end_sent : 1;
59 Eina_Bool exit_read : 1;
60 Eina_Bool exit_called : 1;
61};
62
63//////////////////////////////////////////////////////////////////////////
64
65static void
66_cb_thread_out(void *data, const Efl_Event *event EINA_UNUSED)
67{
68 Eo *obj = data;
69 efl_io_reader_can_read_set(obj, EINA_TRUE);
70}
71
72static void
73_cb_thread_in(void *data, const Efl_Event *event EINA_UNUSED)
74{
75 Eo *obj = data;
76 efl_io_writer_can_write_set(obj, EINA_TRUE);
77}
78
79static void
80_cb_thread_ctrl_out(void *data, const Efl_Event *event EINA_UNUSED)
81{
82 Eo *obj = data;
83 Control_Data cmd;
84 ssize_t ret;
85 Efl_Appthread_Data *ad;
86
87 ad = efl_data_scope_get(obj, EFL_APPTHREAD_CLASS);
88 cmd.command = 0;
89 cmd.data = 0;
90 ret = read(ad->ctrl.out, &cmd, sizeof(Control_Data));
91 if (ret == sizeof(Control_Data))
92 {
93 if (cmd.command == CMD_EXIT)
94 {
95 efl_event_callback_call(obj, EFL_TASK_EVENT_EXIT, NULL);
96 efl_loop_quit(obj, eina_value_int_init(0));
97 }
98 }
99}
100
101static Eina_Value
102_efl_loop_arguments_send(void *data, const Eina_Value v,
103 const Eina_Future *dead EINA_UNUSED)
104
105{
106 Efl_Loop_Arguments arge;
107 Eo *obj = data;
108 Eina_Array *arga;
109 Eina_Stringshare *s;
110 unsigned int argc = efl_task_arg_count_get(obj);
111 unsigned int i;
112
113 arga = eina_array_new(argc);
114 if (v.type == EINA_VALUE_TYPE_ERROR) goto on_error;
115
116 for (i = 0; i < argc; i++)
117 {
118 const char *argv = efl_task_arg_value_get(obj, i);
119 if (argv)
120 eina_array_push(arga, eina_stringshare_add(argv));
121 }
122 arge.argv = arga;
123 arge.initialization = EINA_TRUE;
124 efl_event_callback_call(obj,
125 EFL_LOOP_EVENT_ARGUMENTS, &arge);
126on_error:
127 while ((s = eina_array_pop(arga))) eina_stringshare_del(s);
128 eina_array_free(arga);
129 return v;
130}
131
132static void
133_appthread_parent_read_listeners_modify(Efl_Appthread_Data *ad, int mod)
134{
135 ad->read_listeners += mod;
136
137 if (ad->fd.out_handler)
138 {
139 if ((ad->read_listeners == 0) && (mod < 0))
140 efl_loop_handler_active_set
141 (ad->fd.out_handler, EFL_LOOP_HANDLER_FLAGS_NONE);
142 else if ((ad->read_listeners == 1) && (mod > 0))
143 efl_loop_handler_active_set
144 (ad->fd.out_handler, EFL_LOOP_HANDLER_FLAGS_READ);
145 }
146}
147
148static void
149_cb_appthread_event_callback_add(void *data, const Efl_Event *event)
150{
151 Efl_Appthread_Data *ad = data;
152 const Efl_Callback_Array_Item_Full *array = event->info;
153 int i;
154
155 for (i = 0; array[i].desc != NULL; i++)
156 {
157 if (array[i].desc == EFL_IO_READER_EVENT_CAN_READ_CHANGED)
158 _appthread_parent_read_listeners_modify(ad, 1);
159 }
160}
161
162static void
163_cb_appthread_event_callback_del(void *data, const Efl_Event *event)
164{
165 Efl_Appthread_Data *ad = data;
166 const Efl_Callback_Array_Item_Full *array = event->info;
167 int i;
168
169 for (i = 0; array[i].desc != NULL; i++)
170 {
171 if (array[i].desc == EFL_IO_READER_EVENT_CAN_READ_CHANGED)
172 _appthread_parent_read_listeners_modify(ad, -1);
173 }
174}
175
176EFL_CALLBACKS_ARRAY_DEFINE(_appthread_event_callback_watch,
177 { EFL_EVENT_CALLBACK_ADD, _cb_appthread_event_callback_add },
178 { EFL_EVENT_CALLBACK_DEL, _cb_appthread_event_callback_del });
179
180static void *
181_efl_thread_main(void *data, Eina_Thread t)
182{
183 Efl_Appthread_Data *ad;
184 Thread_Data *thdat = data;
185 Eo *obj;
186 Eina_Value *ret;
187 Control_Data cmd;
188 unsigned int i;
189 int real;
190 Efl_Callback_Array_Item_Full *it;
191 Eina_Future *job;
192
193 if (thdat->name) eina_thread_name_set(t, thdat->name);
194 else eina_thread_name_set(t, "Eflthread");
195
196 obj = efl_add(EFL_APPTHREAD_CLASS, NULL);
197 ad = efl_data_scope_get(obj, EFL_APPTHREAD_CLASS);
198 efl_event_callback_array_add(obj, _appthread_event_callback_watch(), ad);
199
200 // add handlers for "stdio"
201 thdat->fd.in_handler =
202 efl_add(EFL_LOOP_HANDLER_CLASS, obj,
203 efl_loop_handler_fd_set(efl_added, thdat->fd.in),
204 efl_event_callback_add
205 (efl_added, EFL_LOOP_HANDLER_EVENT_WRITE, _cb_thread_in, obj));
206 thdat->fd.out_handler =
207 efl_add(EFL_LOOP_HANDLER_CLASS, obj,
208 efl_loop_handler_fd_set(efl_added, thdat->fd.out),
209 efl_event_callback_add
210 (efl_added, EFL_LOOP_HANDLER_EVENT_READ, _cb_thread_out, obj));
211 // add handlers for control pipes
212 thdat->ctrl.in_handler =
213 efl_add(EFL_LOOP_HANDLER_CLASS, obj,
214 efl_loop_handler_fd_set(efl_added, thdat->ctrl.in));
215 thdat->ctrl.out_handler =
216 efl_add(EFL_LOOP_HANDLER_CLASS, obj,
217 efl_loop_handler_fd_set(efl_added, thdat->ctrl.out),
218 efl_event_callback_add
219 (efl_added, EFL_LOOP_HANDLER_EVENT_READ, _cb_thread_ctrl_out, obj),
220 efl_loop_handler_active_set
221 (efl_added, EFL_LOOP_HANDLER_FLAGS_READ));
222 ad->fd.in = thdat->fd.in;
223 ad->fd.out = thdat->fd.out;
224 ad->ctrl.in = thdat->ctrl.in;
225 ad->ctrl.out = thdat->ctrl.out;
226 ad->fd.in_handler = thdat->fd.in_handler;
227 ad->fd.out_handler = thdat->fd.out_handler;
228 ad->ctrl.in_handler = thdat->ctrl.in_handler;
229 ad->ctrl.out_handler = thdat->ctrl.out_handler;
230
231 if (thdat->event_cb)
232 {
233 for (it = thdat->event_cb; it->func; it++)
234 efl_event_callback_priority_add(obj, it->desc, it->priority,
235 it->func, it->user_data);
236 }
237 for (i = 0; i < thdat->args.argc; i++)
238 efl_task_arg_append(obj, thdat->args.argv[i]);
239 job = eina_future_then(efl_loop_job(obj), _efl_loop_arguments_send, obj);
240 efl_future_Eina_FutureXXX_then(obj, job);
241
242 for (i = 0; i < thdat->args.argc; i++)
243 eina_stringshare_del(thdat->args.argv[i]);
244 free(thdat->args.argv);
245 free(thdat->event_cb);
246 thdat->args.argv = NULL;
247 thdat->event_cb = NULL;
248
249 ret = efl_loop_begin(obj);
250 real = efl_loop_exit_code_process(ret);
251
252 cmd.command = CMD_EXITED;
253 cmd.data = real;
254 write(thdat->ctrl.in, &cmd, sizeof(Control_Data));
255
256 efl_del(obj);
257
258 thdat->fd.in_handler = NULL;
259 thdat->fd.out_handler = NULL;
260 thdat->ctrl.in_handler = NULL;
261 thdat->ctrl.out_handler = NULL;
262 thdat->fd.in = -1;
263 thdat->fd.out = -1;
264 thdat->ctrl.in = -1;
265 thdat->ctrl.out = -1;
266
267 return NULL;
268}
269
270//////////////////////////////////////////////////////////////////////////
271
272static Eina_Value
273_efl_loop_task_exit(void *data, const Eina_Value v,
274 const Eina_Future *dead EINA_UNUSED)
275
276{
277 Eo *obj = data;
278
279 efl_event_callback_call(obj, EFL_TASK_EVENT_EXIT, NULL);
280 efl_unref(obj);
281 return v;
282}
283
284static void
285_thread_exit_eval(Eo *obj, Efl_Thread_Data *pd)
286{
287 if ((pd->fd.out == -1) && /*(pd->fd.in == -1) &&*/
288 (pd->exit_read) && (!pd->exit_called))
289 {
290 Eina_Future *job;
291 Eo *loop = efl_provider_find(obj, EFL_LOOP_CLASS);
292
293 pd->exit_called = EINA_TRUE;
294 efl_ref(obj);
295 job = eina_future_then(efl_loop_job(loop), _efl_loop_task_exit, obj);
296 efl_future_Eina_FutureXXX_then(loop, job);
297 }
298}
299
300static void
301_cb_thread_parent_out(void *data, const Efl_Event *event EINA_UNUSED)
302{
303 Eo *obj = data;
304 efl_io_reader_can_read_set(obj, EINA_TRUE);
305}
306
307static void
308_cb_thread_parent_in(void *data, const Efl_Event *event EINA_UNUSED)
309{
310 Eo *obj = data;
311 efl_io_writer_can_write_set(obj, EINA_TRUE);
312}
313
314static void
315_cb_thread_parent_ctrl_out(void *data, const Efl_Event *event EINA_UNUSED)
316{
317 Eo *obj = data;
318 Control_Data cmd;
319 ssize_t ret;
320 Efl_Thread_Data *pd = efl_data_scope_get(obj, MY_CLASS);
321
322 if (!pd) return;
323
324 cmd.command = 0;
325 cmd.data = 0;
326 ret = read(pd->ctrl.out, &cmd, sizeof(Control_Data));
327 if (ret == sizeof(Control_Data))
328 {
329 if (cmd.command == CMD_EXITED)
330 {
331 if (!pd->exit_read)
332 {
333 Efl_Task_Data *td = efl_data_scope_get(obj, EFL_TASK_CLASS);
334
335 if (td) td->exit_code = cmd.data;
336 pd->exit_read = EINA_TRUE;
337 _thread_exit_eval(obj, pd);
338 }
339 }
340 }
341}
342
343//////////////////////////////////////////////////////////////////////////
344
345static void
346_thread_parent_read_listeners_modify(Efl_Thread_Data *pd, int mod)
347{
348 pd->read_listeners += mod;
349
350 if (pd->fd.out_handler)
351 {
352 if ((pd->read_listeners == 0) && (mod < 0))
353 efl_loop_handler_active_set
354 (pd->fd.out_handler, EFL_LOOP_HANDLER_FLAGS_NONE);
355 else if ((pd->read_listeners == 1) && (mod > 0))
356 efl_loop_handler_active_set
357 (pd->fd.out_handler, EFL_LOOP_HANDLER_FLAGS_READ);
358 }
359}
360
361static void
362_cb_event_callback_add(void *data, const Efl_Event *event)
363{
364 Efl_Thread_Data *pd = data;
365 const Efl_Callback_Array_Item_Full *array = event->info;
366 int i;
367
368 for (i = 0; array[i].desc != NULL; i++)
369 {
370 if (array[i].desc == EFL_LOOP_EVENT_ARGUMENTS)
371 {
372 Efl_Callback_Array_Item_Full *event_cb, *it;
373 int num;
374
375 num = 0;
376 if (pd->event_cb)
377 {
378 for (it = pd->event_cb; it->func; it++) num++;
379 }
380 num++;
381 event_cb = realloc(pd->event_cb, (num + 1) * sizeof(Efl_Callback_Array_Item_Full));
382 if (event_cb)
383 {
384 pd->event_cb = event_cb;
385 event_cb[num - 1] = array[i];
386 event_cb[num].desc = NULL;
387 event_cb[num].priority = 0;
388 event_cb[num].func = NULL;
389 event_cb[num].user_data = NULL;
390 }
391 }
392 else if (array[i].desc == EFL_IO_READER_EVENT_CAN_READ_CHANGED)
393 _thread_parent_read_listeners_modify(pd, 1);
394 }
395}
396
397static void
398_cb_event_callback_del(void *data, const Efl_Event *event)
399{
400 Efl_Thread_Data *pd = data;
401 const Efl_Callback_Array_Item_Full *array = event->info;
402 int i;
403
404 for (i = 0; array[i].desc != NULL; i++)
405 {
406 if (array[i].desc == EFL_LOOP_EVENT_ARGUMENTS)
407 {
408 Efl_Callback_Array_Item_Full *it;
409
410 if (pd->event_cb)
411 {
412 Eina_Bool shuffle_down = EINA_FALSE;
413
414 for (it = pd->event_cb; it->func; it++)
415 {
416 if ((it->desc == array[i].desc) &&
417 (it->priority == array[i].priority) &&
418 (it->func == array[i].func) &&
419 (it->user_data == array[i].user_data))
420 shuffle_down = EINA_TRUE;
421 if (shuffle_down) it[0] = it[1];
422 }
423 }
424 }
425 else if (array[i].desc == EFL_IO_READER_EVENT_CAN_READ_CHANGED)
426 _thread_parent_read_listeners_modify(pd, -1);
427 }
428}
429
430EFL_CALLBACKS_ARRAY_DEFINE(_event_callback_watch,
431 { EFL_EVENT_CALLBACK_ADD, _cb_event_callback_add },
432 { EFL_EVENT_CALLBACK_DEL, _cb_event_callback_del });
433
434//////////////////////////////////////////////////////////////////////////
435
436EOLIAN static Efl_Object *
437_efl_thread_efl_object_constructor(Eo *obj, Efl_Thread_Data *pd)
438{
439 obj = efl_constructor(efl_super(obj, MY_CLASS));
440 efl_event_callback_array_add(obj, _event_callback_watch(), pd);
441 pd->fd.in = -1;
442 pd->fd.out = -1;
443 pd->fd.can_write = EINA_TRUE;
444 pd->ctrl.in = -1;
445 pd->ctrl.out = -1;
446 return obj;
447}
448
449EOLIAN static void
450_efl_thread_efl_object_destructor(Eo *obj, Efl_Thread_Data *pd)
451{
452 if (pd->thdat)
453 {
454/* we probably shouldn't do this... this simply has to orphan threads if they
455 * lose their parent. this stops shutdown from blocking.
456 // if exit response not read yet, read until fetched
457 if (!pd->exit_read)
458 {
459 Control_Data cmd;
460 ssize_t ret;
461
462 // if it hasn't been asked to exit... ask it
463 if (!pd->end_sent) efl_task_end(obj);
464 cmd.command = 0;
465 cmd.data = 0;
466 ret = read(pd->ctrl.out, &cmd, sizeof(Control_Data));
467 while (ret == sizeof(Control_Data))
468 {
469 if (cmd.command == CMD_EXITED)
470 {
471 if (!pd->exit_read)
472 {
473 Efl_Task_Data *td = efl_data_scope_get(obj, EFL_TASK_CLASS);
474
475 if (td) td->exit_code = cmd.data;
476 pd->exit_read = EINA_TRUE;
477 efl_event_callback_call(obj, EFL_TASK_EVENT_EXIT, NULL);
478 break;
479 }
480 }
481 ret = read(pd->ctrl.out, &cmd, sizeof(Control_Data));
482 }
483 }
484 */
485 // stop and wait for thread to exit/join here
486 eina_thread_join(pd->thread);
487 efl_del(pd->fd.in_handler);
488 efl_del(pd->fd.out_handler);
489 efl_del(pd->ctrl.in_handler);
490 efl_del(pd->ctrl.out_handler);
491 close(pd->fd.in);
492 close(pd->fd.out);
493 close(pd->ctrl.in);
494 close(pd->ctrl.out);
495 pd->fd.in_handler = NULL;
496 pd->fd.out_handler = NULL;
497 pd->ctrl.in_handler = NULL;
498 pd->ctrl.out_handler = NULL;
499 pd->fd.in = -1;
500 pd->fd.out = -1;
501 pd->ctrl.in = -1;
502 pd->ctrl.out = -1;
503 free(pd->thdat);
504 }
505 free(pd->event_cb);
506 pd->event_cb = NULL;
507 efl_destructor(efl_super(obj, MY_CLASS));
508}
509
510EOLIAN static void
511_efl_thread_efl_object_parent_set(Eo *obj, Efl_Thread_Data *pd, Efl_Object *parent)
512{
513 efl_parent_set(efl_super(obj, MY_CLASS), parent);
514 pd->loop = efl_provider_find(parent, EFL_LOOP_CLASS);
515}
516
517EOLIAN static Eina_Bool
518_efl_thread_efl_task_run(Eo *obj, Efl_Thread_Data *pd)
519{
520 Eina_Thread_Priority pri;
521 Thread_Data *thdat;
522 const char *name;
523 int pipe_to_thread[2];
524 int pipe_from_thread[2];
525 unsigned int argc, i, num;
526 Efl_Callback_Array_Item_Full *it;
527
528 thdat = calloc(1, sizeof(Thread_Data));
529 if (!thdat) return EINA_FALSE;
530 thdat->fd.in = -1;
531 thdat->fd.out = -1;
532 thdat->ctrl.in = -1;
533 thdat->ctrl.out = -1;
534
535 if (pipe(pipe_to_thread) != 0)
536 {
537 ERR("Can't create to_thread pipe");
538 free(thdat);
539 return EINA_FALSE;
540 }
541 if (pipe(pipe_from_thread) != 0)
542 {
543 ERR("Can't create from_thread pipe");
544 close(pipe_to_thread[0]);
545 close(pipe_to_thread[1]);
546 free(thdat);
547 return EINA_FALSE;
548 }
549 thdat->fd.in = pipe_from_thread[1]; // write - input to parent
550 thdat->fd.out = pipe_to_thread [0]; // read - output from parent
551 pd->fd.in = pipe_to_thread [1]; // write - input to child
552 pd->fd.out = pipe_from_thread[0]; // read - output from child
553 eina_file_close_on_exec(pd->fd.in, EINA_TRUE);
554 eina_file_close_on_exec(pd->fd.out, EINA_TRUE);
555 eina_file_close_on_exec(thdat->fd.in, EINA_TRUE);
556 eina_file_close_on_exec(thdat->fd.out, EINA_TRUE);
557 fcntl(pd->fd.in, F_SETFL, O_NONBLOCK);
558 fcntl(pd->fd.out, F_SETFL, O_NONBLOCK);
559 fcntl(thdat->fd.in, F_SETFL, O_NONBLOCK);
560 fcntl(thdat->fd.out, F_SETFL, O_NONBLOCK);
561 pd->fd.in_handler =
562 efl_add(EFL_LOOP_HANDLER_CLASS, obj,
563 efl_loop_handler_fd_set(efl_added, pd->fd.in),
564 efl_event_callback_add
565 (efl_added, EFL_LOOP_HANDLER_EVENT_WRITE, _cb_thread_parent_in, obj));
566 pd->fd.out_handler =
567 efl_add(EFL_LOOP_HANDLER_CLASS, obj,
568 efl_loop_handler_fd_set(efl_added, pd->fd.out),
569 efl_event_callback_add
570 (efl_added, EFL_LOOP_HANDLER_EVENT_READ, _cb_thread_parent_out, obj));
571 if (pd->read_listeners > 0)
572 efl_loop_handler_active_set(pd->fd.out_handler, EFL_LOOP_HANDLER_FLAGS_READ);
573
574 if (pipe(pipe_to_thread) != 0)
575 {
576 ERR("Can't create to_thread control pipe");
577 efl_del(pd->fd.in_handler);
578 efl_del(pd->fd.out_handler);
579 close(thdat->fd.in);
580 close(thdat->fd.out);
581 close(pd->fd.in);
582 close(pd->fd.out);
583 pd->fd.in_handler = NULL;
584 pd->fd.out_handler = NULL;
585 pd->fd.in = -1;
586 pd->fd.out = -1;
587 free(thdat);
588 return EINA_FALSE;
589 }
590 if (pipe(pipe_from_thread) != 0)
591 {
592 ERR("Can't create from_thread control pipe");
593 efl_del(pd->fd.in_handler);
594 efl_del(pd->fd.out_handler);
595 close(pipe_to_thread[0]);
596 close(pipe_to_thread[1]);
597 close(thdat->fd.in);
598 close(thdat->fd.out);
599 close(pd->fd.in);
600 close(pd->fd.out);
601 pd->fd.in_handler = NULL;
602 pd->fd.out_handler = NULL;
603 pd->fd.in = -1;
604 pd->fd.out = -1;
605 free(thdat);
606 return EINA_FALSE;
607 }
608 thdat->ctrl.in = pipe_from_thread[1]; // write - input to parent
609 thdat->ctrl.out = pipe_to_thread [0]; // read - output from parent
610 pd->ctrl.in = pipe_to_thread [1]; // write - input to child
611 pd->ctrl.out = pipe_from_thread[0]; // read - output from child
612 // yes - these are blocking because we write and read very little
613 eina_file_close_on_exec(pd->ctrl.in, EINA_TRUE);
614 eina_file_close_on_exec(pd->ctrl.out, EINA_TRUE);
615 eina_file_close_on_exec(thdat->ctrl.in, EINA_TRUE);
616 eina_file_close_on_exec(thdat->ctrl.out, EINA_TRUE);
617 pd->ctrl.in_handler =
618 efl_add(EFL_LOOP_HANDLER_CLASS, obj,
619 efl_loop_handler_fd_set(efl_added, pd->ctrl.in));
620 pd->ctrl.out_handler =
621 efl_add(EFL_LOOP_HANDLER_CLASS, obj,
622 efl_loop_handler_fd_set(efl_added, pd->ctrl.out),
623 efl_event_callback_add
624 (efl_added, EFL_LOOP_HANDLER_EVENT_READ, _cb_thread_parent_ctrl_out, obj),
625 efl_loop_handler_active_set
626 (efl_added, EFL_LOOP_HANDLER_FLAGS_READ));
627
628 switch (efl_task_priority_get(obj))
629 {
630 case EFL_TASK_PRIORITY_BACKGROUND:
631 pri = EINA_THREAD_IDLE;
632 break;
633 case EFL_TASK_PRIORITY_HIGH:
634 case EFL_TASK_PRIORITY_ULTRA:
635 pri = EINA_THREAD_URGENT;
636 break;
637 case EFL_TASK_PRIORITY_LOW:
638 pri = EINA_THREAD_BACKGROUND;
639 break;
640 case EFL_TASK_PRIORITY_NORMAL:
641 default:
642 pri = EINA_THREAD_NORMAL;
643 break;
644 }
645 name = efl_name_get(obj);
646 if (name) thdat->name = eina_stringshare_add(name);
647
648 argc = efl_task_arg_count_get(obj);
649 if (argc > 0)
650 {
651 thdat->args.argc = argc;
652 thdat->args.argv = malloc(argc * sizeof(char *));
653 if (thdat->args.argv)
654 {
655 for (i = 0; i < argc; i++)
656 {
657 const char *argv = efl_task_arg_value_get(obj, i);
658 if (argv)
659 thdat->args.argv[i] = eina_stringshare_add(argv);
660 else
661 thdat->args.argv[i] = NULL;
662 }
663 }
664 // XXX: if malloc fails?
665 }
666 if (pd->event_cb)
667 {
668 num = 0;
669 for (it = pd->event_cb; it->func; it++) num++;
670 thdat->event_cb = malloc((num + 1) * sizeof(Efl_Callback_Array_Item_Full));
671 if (thdat->event_cb)
672 memcpy(thdat->event_cb, pd->event_cb,
673 (num + 1) * sizeof(Efl_Callback_Array_Item_Full));
674 // XXX: if malloc fails?
675 }
676
677 // env data - ignore as other end will share same env
678
679 if (!eina_thread_create(&(pd->thread), pri, -1, _efl_thread_main, thdat))
680 {
681 for (i = 0; i < thdat->args.argc; i++)
682 eina_stringshare_del(thdat->args.argv[i]);
683 free(thdat->args.argv);
684 efl_del(pd->fd.in_handler);
685 efl_del(pd->fd.out_handler);
686 efl_del(pd->ctrl.in_handler);
687 efl_del(pd->ctrl.out_handler);
688 close(pd->fd.in);
689 close(pd->fd.out);
690 close(pd->ctrl.in);
691 close(pd->ctrl.out);
692 close(thdat->fd.in);
693 close(thdat->fd.out);
694 close(thdat->ctrl.in);
695 close(thdat->ctrl.out);
696 free(thdat);
697 pd->fd.in_handler = NULL;
698 pd->fd.out_handler = NULL;
699 pd->ctrl.in_handler = NULL;
700 pd->ctrl.out_handler = NULL;
701 pd->fd.in = -1;
702 pd->fd.out = -1;
703 pd->ctrl.in = -1;
704 pd->ctrl.out = -1;
705 return EINA_FALSE;
706 }
707 pd->thdat = thdat;
708 return EINA_TRUE;
709}
710
711EOLIAN static void
712_efl_thread_efl_task_end(Eo *obj EINA_UNUSED, Efl_Thread_Data *pd)
713{
714 if (pd->end_sent) return;
715 if (pd->thdat)
716 {
717 Control_Data cmd;
718
719 pd->end_sent = EINA_TRUE;
720 cmd.command = CMD_EXIT;
721 cmd.data = 0;
722 write(pd->ctrl.in, &cmd, sizeof(Control_Data));
723 }
724}
725
726EOLIAN static Eina_Error
727_efl_thread_efl_io_closer_close(Eo *obj, Efl_Thread_Data *pd)
728{
729 if (!pd->thdat) return 0;
730 EINA_SAFETY_ON_TRUE_RETURN_VAL(efl_io_closer_closed_get(obj), EBADF);
731 efl_io_writer_can_write_set(obj, EINA_FALSE);
732 efl_io_reader_can_read_set(obj, EINA_FALSE);
733 efl_io_reader_eos_set(obj, EINA_TRUE);
734 if (pd->fd.in >= 0) close(pd->fd.in);
735 if (pd->fd.out >= 0) close(pd->fd.out);
736 if (pd->fd.in_handler) efl_del(pd->fd.in_handler);
737 if (pd->fd.out_handler) efl_del(pd->fd.out_handler);
738 pd->fd.in = -1;
739 pd->fd.out = -1;
740 pd->fd.in_handler = NULL;
741 pd->fd.out_handler = NULL;
742 return 0;
743}
744
745EOLIAN static Eina_Bool
746_efl_thread_efl_io_closer_closed_get(Eo *obj EINA_UNUSED, Efl_Thread_Data *pd)
747{
748 if ((pd->fd.in == -1) && (pd->fd.out == -1)) return EINA_TRUE;
749 return EINA_FALSE;
750}
751
752EOLIAN static Eina_Error
753_efl_thread_efl_io_reader_read(Eo *obj, Efl_Thread_Data *pd, Eina_Rw_Slice *rw_slice)
754{
755 ssize_t r;
756
757 errno = 0;
758 if (pd->fd.out == -1) goto err;
759
760 do
761 {
762 errno = 0;
763 r = read(pd->fd.out, rw_slice->mem, rw_slice->len);
764 if (r == -1)
765 {
766 if (errno == EINTR) continue;
767 goto err;
768 }
769 }
770 while (r == -1);
771
772 rw_slice->len = r;
773 if (r == 0)
774 {
775 efl_io_reader_can_read_set(obj, EINA_FALSE);
776 efl_io_reader_eos_set(obj, EINA_TRUE);
777 close(pd->fd.out);
778 pd->fd.out = -1;
779 efl_del(pd->fd.out_handler);
780 pd->fd.out_handler = NULL;
781 _thread_exit_eval(obj, pd);
782 return EPIPE;
783 }
784 return 0;
785err:
786 if ((pd->fd.out != -1) && (errno != EAGAIN))
787 {
788 close(pd->fd.out);
789 pd->fd.out = -1;
790 efl_del(pd->fd.out_handler);
791 pd->fd.out_handler = NULL;
792 }
793 rw_slice->len = 0;
794 rw_slice->mem = NULL;
795 efl_io_reader_can_read_set(obj, EINA_FALSE);
796 _thread_exit_eval(obj, pd);
797 return EINVAL;
798}
799
800EOLIAN static void
801_efl_thread_efl_io_reader_can_read_set(Eo *obj, Efl_Thread_Data *pd, Eina_Bool can_read)
802{
803 Eina_Bool old = efl_io_reader_can_read_get(obj);
804 if (old == can_read) return;
805 pd->fd.can_read = can_read;
806 if (!pd->fd.out_handler) return;
807 if (can_read)
808 efl_loop_handler_active_set(pd->fd.out_handler, 0);
809 else
810 efl_loop_handler_active_set(pd->fd.out_handler,
811 EFL_LOOP_HANDLER_FLAGS_READ);
812 efl_event_callback_call(obj, EFL_IO_READER_EVENT_CAN_READ_CHANGED, NULL);
813}
814
815EOLIAN static Eina_Bool
816_efl_thread_efl_io_reader_can_read_get(Eo *obj EINA_UNUSED, Efl_Thread_Data *pd)
817{
818 return pd->fd.can_read;
819}
820
821EOLIAN static void
822_efl_thread_efl_io_reader_eos_set(Eo *obj, Efl_Thread_Data *pd, Eina_Bool is_eos)
823{
824 Eina_Bool old = efl_io_reader_eos_get(obj);
825 if (old == is_eos) return;
826
827 pd->fd.eos_read = is_eos;
828 if (!is_eos) return;
829 if (pd->fd.out_handler)
830 efl_loop_handler_active_set(pd->fd.out_handler, 0);
831 efl_event_callback_call(obj, EFL_IO_READER_EVENT_EOS, NULL);
832}
833
834EOLIAN static Eina_Bool
835_efl_thread_efl_io_reader_eos_get(Eo *obj EINA_UNUSED, Efl_Thread_Data *pd)
836{
837 return pd->fd.eos_read;
838}
839
840EOLIAN static Eina_Error
841_efl_thread_efl_io_writer_write(Eo *obj, Efl_Thread_Data *pd, Eina_Slice *slice, Eina_Slice *remaining)
842{
843 ssize_t r;
844
845 errno = 0;
846 if (pd->fd.in == -1) goto err;
847
848 do
849 {
850 errno = 0;
851 r = write(pd->fd.in, slice->mem, slice->len);
852 if (r == -1)
853 {
854 if (errno == EINTR) continue;
855 goto err;
856 }
857 }
858 while (r == -1);
859
860 if (remaining)
861 {
862 remaining->len = slice->len - r;
863 remaining->bytes = slice->bytes + r;
864 }
865 slice->len = r;
866
867 if ((slice) && (slice->len > 0))
868 efl_io_writer_can_write_set(obj, EINA_FALSE);
869 if (r == 0)
870 {
871 close(pd->fd.in);
872 pd->fd.in = -1;
873 efl_del(pd->fd.in_handler);
874 pd->fd.in_handler = NULL;
875 _thread_exit_eval(obj, pd);
876 return EPIPE;
877 }
878 return 0;
879err:
880 if ((pd->fd.in != -1) && (errno != EAGAIN))
881 {
882 close(pd->fd.in);
883 pd->fd.in = -1;
884 efl_del(pd->fd.in_handler);
885 pd->fd.in_handler = NULL;
886 }
887 if (remaining) *remaining = *slice;
888 slice->len = 0;
889 slice->mem = NULL;
890 efl_io_writer_can_write_set(obj, EINA_FALSE);
891 _thread_exit_eval(obj, pd);
892 return EINVAL;
893}
894
895EOLIAN static void
896_efl_thread_efl_io_writer_can_write_set(Eo *obj, Efl_Thread_Data *pd, Eina_Bool can_write)
897{
898 Eina_Bool old = efl_io_writer_can_write_get(obj);
899 if (old == can_write) return;
900 pd->fd.can_write = can_write;
901 if (can_write)
902 efl_loop_handler_active_set(pd->fd.in_handler, 0);
903 else
904 efl_loop_handler_active_set(pd->fd.in_handler,
905 EFL_LOOP_HANDLER_FLAGS_WRITE);
906 efl_event_callback_call(obj, EFL_IO_WRITER_EVENT_CAN_WRITE_CHANGED, NULL);
907}
908
909EOLIAN static Eina_Bool
910_efl_thread_efl_io_writer_can_write_get(Eo *obj EINA_UNUSED, Efl_Thread_Data *pd)
911{
912 return pd->fd.can_write;
913}
914
915//////////////////////////////////////////////////////////////////////////
916
917#include "efl_thread.eo.c"
diff --git a/src/lib/ecore/efl_thread.eo b/src/lib/ecore/efl_thread.eo
index 63b7292131..214c0fd07f 100644
--- a/src/lib/ecore/efl_thread.eo
+++ b/src/lib/ecore/efl_thread.eo
@@ -8,5 +8,15 @@ class Efl.Thread (Efl.Task)
8 implements { 8 implements {
9 Efl.Object.constructor; 9 Efl.Object.constructor;
10 Efl.Object.destructor; 10 Efl.Object.destructor;
11 Efl.Object.parent { set; }
12 Efl.Task.run;
13 Efl.Task.end;
14 Efl.Io.Closer.close;
15 Efl.Io.Closer.closed { get; }
16 Efl.Io.Reader.read;
17 Efl.Io.Reader.can_read { get; set; }
18 Efl.Io.Reader.eos { get; set; }
19 Efl.Io.Writer.write;
20 Efl.Io.Writer.can_write { get; set; }
11 } 21 }
12} 22}
diff --git a/src/lib/ecore_evas/ecore_evas.c b/src/lib/ecore_evas/ecore_evas.c
index 67ab7e9fd0..4348da8084 100644
--- a/src/lib/ecore_evas/ecore_evas.c
+++ b/src/lib/ecore_evas/ecore_evas.c
@@ -3195,7 +3195,7 @@ _ecore_evas_animator_fallback(void *data)
3195static void 3195static void
3196_check_animator_event_catcher_add(void *data, const Efl_Event *event) 3196_check_animator_event_catcher_add(void *data, const Efl_Event *event)
3197{ 3197{
3198 const Efl_Callback_Array_Item *array = event->info; 3198 const Efl_Callback_Array_Item_Full *array = event->info;
3199 Ecore_Evas *ee = data; 3199 Ecore_Evas *ee = data;
3200 int i; 3200 int i;
3201 3201
@@ -3229,7 +3229,7 @@ _check_animator_event_catcher_add(void *data, const Efl_Event *event)
3229static void 3229static void
3230_check_animator_event_catcher_del(void *data, const Efl_Event *event) 3230_check_animator_event_catcher_del(void *data, const Efl_Event *event)
3231{ 3231{
3232 const Efl_Callback_Array_Item *array = event->info; 3232 const Efl_Callback_Array_Item_Full *array = event->info;
3233 Ecore_Evas *ee = data; 3233 Ecore_Evas *ee = data;
3234 int i; 3234 int i;
3235 3235
diff --git a/src/lib/eina/eina_internal.h b/src/lib/eina/eina_internal.h
index 9324118c91..83e6f5da61 100644
--- a/src/lib/eina/eina_internal.h
+++ b/src/lib/eina/eina_internal.h
@@ -71,6 +71,8 @@ struct _Eina_Vpath_Interface_User
71 */ 71 */
72EAPI void __eina_promise_cancel_all(void); 72EAPI void __eina_promise_cancel_all(void);
73 73
74EAPI void __eina_promise_cancel_data(void *data);
75
74/** 76/**
75 * Make the app specific paths accessable as virtual path 77 * Make the app specific paths accessable as virtual path
76 * 78 *
diff --git a/src/lib/eina/eina_promise.c b/src/lib/eina/eina_promise.c
index c3b488d223..93e091bd9e 100644
--- a/src/lib/eina/eina_promise.c
+++ b/src/lib/eina/eina_promise.c
@@ -566,6 +566,27 @@ __eina_promise_cancel_all(void)
566 eina_lock_release(&_pending_futures_lock); 566 eina_lock_release(&_pending_futures_lock);
567} 567}
568 568
569EAPI void
570__eina_promise_cancel_data(void *data)
571{
572 Eina_List *del = NULL, *l;
573 Eina_Future *f;
574
575 eina_lock_take(&_pending_futures_lock);
576 EINA_LIST_FOREACH(_pending_futures, l, f)
577 {
578 if (f->data == data)
579 {
580 del = eina_list_append(del, f);
581 }
582 }
583 EINA_LIST_FREE(del, f)
584 {
585 _eina_future_cancel(f, ECANCELED);
586 }
587 eina_lock_release(&_pending_futures_lock);
588}
589
569Eina_Bool 590Eina_Bool
570eina_promise_shutdown(void) 591eina_promise_shutdown(void)
571{ 592{
diff --git a/src/lib/elementary/efl_ui_text.c b/src/lib/elementary/efl_ui_text.c
index 98dda2afea..b8fa0ea20e 100644
--- a/src/lib/elementary/efl_ui_text.c
+++ b/src/lib/elementary/efl_ui_text.c
@@ -2975,9 +2975,10 @@ _efl_ui_text_efl_canvas_group_group_member_add(Eo *obj, Efl_Ui_Text_Data *sd, Ev
2975static void 2975static void
2976_cb_added(void *data EINA_UNUSED, const Efl_Event *ev) 2976_cb_added(void *data EINA_UNUSED, const Efl_Event *ev)
2977{ 2977{
2978 const Efl_Callback_Array_Item *event = ev->info; 2978 const Efl_Callback_Array_Item_Full *event = ev->info;
2979 2979
2980 EFL_UI_TEXT_DATA_GET(ev->object, sd); 2980 EFL_UI_TEXT_DATA_GET(ev->object, sd);
2981 // XXX: BUG - not walking the array until a NULL entry
2981 if (event->desc == EFL_UI_TEXT_EVENT_VALIDATE) 2982 if (event->desc == EFL_UI_TEXT_EVENT_VALIDATE)
2982 sd->validators++; 2983 sd->validators++;
2983} 2984}
@@ -2985,9 +2986,10 @@ _cb_added(void *data EINA_UNUSED, const Efl_Event *ev)
2985static void 2986static void
2986_cb_deleted(void *data EINA_UNUSED, const Efl_Event *ev) 2987_cb_deleted(void *data EINA_UNUSED, const Efl_Event *ev)
2987{ 2988{
2988 const Efl_Callback_Array_Item *event = ev->info; 2989 const Efl_Callback_Array_Item_Full *event = ev->info;
2989 2990
2990 EFL_UI_TEXT_DATA_GET(ev->object, sd); 2991 EFL_UI_TEXT_DATA_GET(ev->object, sd);
2992 // XXX: BUG - not walking the array until a NULL entry
2991 if (event->desc == EFL_UI_TEXT_EVENT_VALIDATE) 2993 if (event->desc == EFL_UI_TEXT_EVENT_VALIDATE)
2992 sd->validators--; 2994 sd->validators--;
2993 return; 2995 return;
diff --git a/src/lib/elementary/efl_ui_win.c b/src/lib/elementary/efl_ui_win.c
index f9f9723d8e..0059cfb9b0 100644
--- a/src/lib/elementary/efl_ui_win.c
+++ b/src/lib/elementary/efl_ui_win.c
@@ -1904,7 +1904,7 @@ _elm_win_evas_device_changed(void *data,
1904static void 1904static void
1905_win_event_add_cb(void *data, const Efl_Event *ev) 1905_win_event_add_cb(void *data, const Efl_Event *ev)
1906{ 1906{
1907 const Efl_Callback_Array_Item *array = ev->info; 1907 const Efl_Callback_Array_Item_Full *array = ev->info;
1908 Efl_Ui_Win_Data *sd = data; 1908 Efl_Ui_Win_Data *sd = data;
1909 Efl_Ui_Win *win = ev->object; 1909 Efl_Ui_Win *win = ev->object;
1910 int i; 1910 int i;
@@ -2035,7 +2035,7 @@ _win_event_add_cb(void *data, const Efl_Event *ev)
2035static void 2035static void
2036_win_event_del_cb(void *data, const Efl_Event *ev) 2036_win_event_del_cb(void *data, const Efl_Event *ev)
2037{ 2037{
2038 const Efl_Callback_Array_Item *array = ev->info; 2038 const Efl_Callback_Array_Item_Full *array = ev->info;
2039 Efl_Ui_Win_Data *sd = data; 2039 Efl_Ui_Win_Data *sd = data;
2040 Efl_Ui_Win *win = ev->object; 2040 Efl_Ui_Win *win = ev->object;
2041 int i; 2041 int i;
@@ -2177,7 +2177,7 @@ _win_paused(void *data, const Efl_Event *ev)
2177 _paused_windows++; 2177 _paused_windows++;
2178 2178
2179 if (_elm_win_count == _paused_windows) 2179 if (_elm_win_count == _paused_windows)
2180 efl_event_callback_call(efl_loop_get(ev->object), EFL_LOOP_EVENT_PAUSE, NULL); 2180 efl_event_callback_call(efl_loop_get(ev->object), EFL_APP_EVENT_PAUSE, NULL);
2181} 2181}
2182 2182
2183EFL_CALLBACKS_ARRAY_DEFINE(_elm_win_tracking, 2183EFL_CALLBACKS_ARRAY_DEFINE(_elm_win_tracking,
@@ -2205,7 +2205,7 @@ _elm_win_resume(void *data, const Efl_Event *ev)
2205 sd->paused = EINA_FALSE; 2205 sd->paused = EINA_FALSE;
2206 2206
2207 if (_elm_win_count == _paused_windows) 2207 if (_elm_win_count == _paused_windows)
2208 efl_event_callback_call(efl_loop_get(ev->object), EFL_LOOP_EVENT_RESUME, NULL); 2208 efl_event_callback_call(efl_loop_get(ev->object), EFL_APP_EVENT_RESUME, NULL);
2209 2209
2210 _paused_windows--; 2210 _paused_windows--;
2211} 2211}
@@ -2831,7 +2831,7 @@ _efl_ui_win_efl_canvas_group_group_del(Eo *obj, Efl_Ui_Win_Data *sd)
2831 _elm_win_state_eval_queue(); 2831 _elm_win_state_eval_queue();
2832 2832
2833 if (_elm_win_count == _paused_windows) 2833 if (_elm_win_count == _paused_windows)
2834 efl_event_callback_call(efl_loop_get(obj), EFL_LOOP_EVENT_PAUSE, NULL); 2834 efl_event_callback_call(efl_loop_get(obj), EFL_APP_EVENT_PAUSE, NULL);
2835 2835
2836 if (sd->ee) 2836 if (sd->ee)
2837 { 2837 {
@@ -5474,7 +5474,7 @@ _efl_ui_win_efl_object_finalize(Eo *obj, Efl_Ui_Win_Data *sd)
5474 obj = _elm_win_finalize_internal(obj, sd, sd->name, sd->type); 5474 obj = _elm_win_finalize_internal(obj, sd, sd->name, sd->type);
5475 if (!obj) return NULL; 5475 if (!obj) return NULL;
5476 obj = efl_finalize(efl_super(obj, MY_CLASS)); 5476 obj = efl_finalize(efl_super(obj, MY_CLASS));
5477 if (obj && resume) efl_event_callback_call(efl_loop_get(obj), EFL_LOOP_EVENT_RESUME, NULL); 5477 if (obj && resume) efl_event_callback_call(efl_loop_get(obj), EFL_APP_EVENT_RESUME, NULL);
5478 return obj; 5478 return obj;
5479} 5479}
5480 5480
diff --git a/src/lib/elementary/elm_entry.c b/src/lib/elementary/elm_entry.c
index 0b61f24124..eff0bbfa65 100644
--- a/src/lib/elementary/elm_entry.c
+++ b/src/lib/elementary/elm_entry.c
@@ -4061,9 +4061,10 @@ elm_entry_add(Evas_Object *parent)
4061static void 4061static void
4062_cb_added(void *data EINA_UNUSED, const Efl_Event *ev) 4062_cb_added(void *data EINA_UNUSED, const Efl_Event *ev)
4063{ 4063{
4064 const Efl_Callback_Array_Item *event = ev->info; 4064 const Efl_Callback_Array_Item_Full *event = ev->info;
4065 4065
4066 ELM_ENTRY_DATA_GET(ev->object, sd); 4066 ELM_ENTRY_DATA_GET(ev->object, sd);
4067 // XXX: BUG - not walking the array until a NULL entry
4067 if (event->desc == ELM_ENTRY_EVENT_VALIDATE) 4068 if (event->desc == ELM_ENTRY_EVENT_VALIDATE)
4068 sd->validators++; 4069 sd->validators++;
4069} 4070}
@@ -4071,9 +4072,10 @@ _cb_added(void *data EINA_UNUSED, const Efl_Event *ev)
4071static void 4072static void
4072_cb_deleted(void *data EINA_UNUSED, const Efl_Event *ev) 4073_cb_deleted(void *data EINA_UNUSED, const Efl_Event *ev)
4073{ 4074{
4074 const Efl_Callback_Array_Item *event = ev->info; 4075 const Efl_Callback_Array_Item_Full *event = ev->info;
4075 4076
4076 ELM_ENTRY_DATA_GET(ev->object, sd); 4077 ELM_ENTRY_DATA_GET(ev->object, sd);
4078 // XXX: BUG - not walking the array until a NULL entry
4077 if (event->desc == ELM_ENTRY_EVENT_VALIDATE) 4079 if (event->desc == ELM_ENTRY_EVENT_VALIDATE)
4078 sd->validators--; 4080 sd->validators--;
4079 return; 4081 return;
diff --git a/src/lib/elementary/elm_main.c b/src/lib/elementary/elm_main.c
index 646b2ee474..82efe0a3c7 100644
--- a/src/lib/elementary/elm_main.c
+++ b/src/lib/elementary/elm_main.c
@@ -927,8 +927,8 @@ static void (*qre_terminate)(void *data,
927 927
928EFL_CALLBACKS_ARRAY_DEFINE(_qre_main_ex, 928EFL_CALLBACKS_ARRAY_DEFINE(_qre_main_ex,
929 { EFL_LOOP_EVENT_ARGUMENTS, qre_main }, 929 { EFL_LOOP_EVENT_ARGUMENTS, qre_main },
930 { EFL_LOOP_EVENT_PAUSE, qre_pause }, 930 { EFL_APP_EVENT_PAUSE, qre_pause },
931 { EFL_LOOP_EVENT_RESUME, qre_resume }, 931 { EFL_APP_EVENT_RESUME, qre_resume },
932 { EFL_EVENT_DEL, qre_terminate }); 932 { EFL_EVENT_DEL, qre_terminate });
933 933
934EAPI Eina_Bool 934EAPI Eina_Bool
@@ -1304,12 +1304,12 @@ elm_policy_set(unsigned int policy,
1304 { 1304 {
1305 if (value == ELM_POLICY_EXIT_WINDOWS_DEL) 1305 if (value == ELM_POLICY_EXIT_WINDOWS_DEL)
1306 { 1306 {
1307 efl_event_callback_add(efl_main_loop_get(), EFL_LOOP_EVENT_TERMINATE, 1307 efl_event_callback_add(efl_main_loop_get(), EFL_APP_EVENT_TERMINATE,
1308 _on_terminate, NULL); 1308 _on_terminate, NULL);
1309 } 1309 }
1310 else 1310 else
1311 { 1311 {
1312 efl_event_callback_del(efl_main_loop_get(), EFL_LOOP_EVENT_TERMINATE, 1312 efl_event_callback_del(efl_main_loop_get(), EFL_APP_EVENT_TERMINATE,
1313 _on_terminate, NULL); 1313 _on_terminate, NULL);
1314 } 1314 }
1315 } 1315 }
diff --git a/src/lib/eo/Eo.h b/src/lib/eo/Eo.h
index 441b3789fc..7c20daaccb 100644
--- a/src/lib/eo/Eo.h
+++ b/src/lib/eo/Eo.h
@@ -241,10 +241,25 @@ typedef short Efl_Callback_Priority;
241 */ 241 */
242typedef struct _Efl_Callback_Array_Item 242typedef struct _Efl_Callback_Array_Item
243{ 243{
244 const Efl_Event_Description *desc; /**< The event description. */ 244 const Efl_Event_Description *desc; /**< The event description. */
245 Efl_Event_Cb func; /**< The callback function. */ 245 Efl_Event_Cb func; /**< The callback function. */
246} Efl_Callback_Array_Item; 246} Efl_Callback_Array_Item;
247 247
248
249/**
250 * @struct _Efl_Callback_Array_Item_Full
251 * @brief An item provided by EFL_EVENT_CALLBACK_ADD/EFL_EVENT_CALLBACK_DEL.
252 *
253 * See also EFL_EVENT_CALLBACK_ADD EFL_EVENT_CALLBACK_DEL.
254 */
255typedef struct _Efl_Callback_Array_Item_Full
256{
257 const Efl_Event_Description *desc; /**< The event description. */
258 Efl_Callback_Priority priority; /** < The priorit of the event */
259 Efl_Event_Cb func; /**< The callback function. */
260 void *user_data; /**< The user data pointer to be passed to the func */
261} Efl_Callback_Array_Item_Full;
262
248/** 263/**
249 * @brief Add a callback for an event with a specific priority. 264 * @brief Add a callback for an event with a specific priority.
250 * 265 *
diff --git a/src/lib/eo/eo_base_class.c b/src/lib/eo/eo_base_class.c
index ca38e7b171..f1eff91f3e 100644
--- a/src/lib/eo/eo_base_class.c
+++ b/src/lib/eo/eo_base_class.c
@@ -1228,7 +1228,8 @@ _efl_object_event_callback_priority_add(Eo *obj, Efl_Object_Data *pd,
1228 Efl_Event_Cb func, 1228 Efl_Event_Cb func,
1229 const void *user_data) 1229 const void *user_data)
1230{ 1230{
1231 const Efl_Callback_Array_Item arr[] = { {desc, func}, {NULL, NULL}}; 1231 const Efl_Callback_Array_Item_Full arr[] =
1232 { {desc, priority, func, (void *)user_data}, {NULL, 0, NULL, NULL}};
1232 Eo_Callback_Description *cb = _eo_callback_new(); 1233 Eo_Callback_Description *cb = _eo_callback_new();
1233 1234
1234 // very unlikely so improve l1 instr cache by using goto 1235 // very unlikely so improve l1 instr cache by using goto
@@ -1265,7 +1266,7 @@ EOAPI EFL_FUNC_BODYV(efl_event_callback_priority_add,
1265 1266
1266static void 1267static void
1267_efl_object_event_callback_clean(Eo *obj, Efl_Object_Data *pd, 1268_efl_object_event_callback_clean(Eo *obj, Efl_Object_Data *pd,
1268 const Efl_Callback_Array_Item *array, 1269 const Efl_Callback_Array_Item_Full *array,
1269 Eo_Callback_Description **cb) 1270 Eo_Callback_Description **cb)
1270{ 1271{
1271 (*cb)->delete_me = EINA_TRUE; 1272 (*cb)->delete_me = EINA_TRUE;
@@ -1295,7 +1296,8 @@ _efl_object_event_callback_del(Eo *obj, Efl_Object_Data *pd,
1295 ((*cb)->items.item.func == func) && 1296 ((*cb)->items.item.func == func) &&
1296 ((*cb)->func_data == user_data)) 1297 ((*cb)->func_data == user_data))
1297 { 1298 {
1298 const Efl_Callback_Array_Item arr[] = { {desc, func}, {NULL, NULL}}; 1299 const Efl_Callback_Array_Item_Full arr[] =
1300 { {desc, (*cb)->priority, func, (*cb)->func_data}, {NULL, 0, NULL, NULL}};
1299 1301
1300 _efl_object_event_callback_clean(obj, pd, arr, cb); 1302 _efl_object_event_callback_clean(obj, pd, arr, cb);
1301 return EINA_TRUE; 1303 return EINA_TRUE;
@@ -1318,9 +1320,9 @@ _efl_object_event_callback_array_priority_add(Eo *obj, Efl_Object_Data *pd,
1318 const void *user_data) 1320 const void *user_data)
1319{ 1321{
1320 Eo_Callback_Description *cb = _eo_callback_new(); 1322 Eo_Callback_Description *cb = _eo_callback_new();
1321#if defined(EFL_EVENT_SPECIAL_SKIP) || defined(EO_DEBUG)
1322 const Efl_Callback_Array_Item *it; 1323 const Efl_Callback_Array_Item *it;
1323#endif 1324 unsigned int num, i;
1325 Efl_Callback_Array_Item_Full *ev_array;
1324#ifdef EO_DEBUG 1326#ifdef EO_DEBUG
1325 const Efl_Callback_Array_Item *prev; 1327 const Efl_Callback_Array_Item *prev;
1326#endif 1328#endif
@@ -1363,7 +1365,21 @@ _efl_object_event_callback_array_priority_add(Eo *obj, Efl_Object_Data *pd,
1363 } 1365 }
1364#endif 1366#endif
1365 1367
1366 efl_event_callback_call(obj, EFL_EVENT_CALLBACK_ADD, (void *)array); 1368 num = 0;
1369 for (it = cb->items.item_array; it->func; it++) num++;
1370 ev_array = alloca((num + 1) * sizeof(Efl_Callback_Array_Item_Full));
1371 for (i = 0, it = cb->items.item_array; it->func; it++, i++)
1372 {
1373 ev_array[i].desc = cb->items.item_array[i].desc;
1374 ev_array[i].priority = cb->priority;
1375 ev_array[i].func = cb->items.item_array[i].func;
1376 ev_array[i].user_data = cb->func_data;
1377 }
1378 ev_array[i].desc = NULL;
1379 ev_array[i].priority = 0;
1380 ev_array[i].func = NULL;
1381 ev_array[i].user_data = NULL;
1382 efl_event_callback_call(obj, EFL_EVENT_CALLBACK_ADD, ev_array);
1367 1383
1368 return EINA_TRUE; 1384 return EINA_TRUE;
1369 1385
@@ -1384,17 +1400,35 @@ _efl_object_event_callback_array_del(Eo *obj, Efl_Object_Data *pd,
1384 const void *user_data) 1400 const void *user_data)
1385{ 1401{
1386 Eo_Callback_Description **cb; 1402 Eo_Callback_Description **cb;
1387 unsigned int i; 1403 unsigned int j;
1388 1404
1389 for (cb = pd->callbacks, i = 0; 1405 for (cb = pd->callbacks, j = 0;
1390 i < pd->callbacks_count; 1406 j < pd->callbacks_count;
1391 cb++, i++) 1407 cb++, j++)
1392 { 1408 {
1393 if (!(*cb)->delete_me && 1409 if (!(*cb)->delete_me &&
1394 ((*cb)->items.item_array == array) && 1410 ((*cb)->items.item_array == array) &&
1395 ((*cb)->func_data == user_data)) 1411 ((*cb)->func_data == user_data))
1396 { 1412 {
1397 _efl_object_event_callback_clean(obj, pd, array, cb); 1413 const Efl_Callback_Array_Item *it;
1414 unsigned int num, i;
1415 Efl_Callback_Array_Item_Full *ev_array;
1416
1417 num = 0;
1418 for (it = (*cb)->items.item_array; it->func; it++) num++;
1419 ev_array = alloca((num + 1) * sizeof(Efl_Callback_Array_Item_Full));
1420 for (i = 0, it = (*cb)->items.item_array; it->func; it++, i++)
1421 {
1422 ev_array[i].desc = (*cb)->items.item_array[i].desc;
1423 ev_array[i].priority = (*cb)->priority;
1424 ev_array[i].func = (*cb)->items.item_array[i].func;
1425 ev_array[i].user_data = (*cb)->func_data;
1426 }
1427 ev_array[i].desc = NULL;
1428 ev_array[i].priority = 0;
1429 ev_array[i].func = NULL;
1430 ev_array[i].user_data = NULL;
1431 _efl_object_event_callback_clean(obj, pd, ev_array, cb);
1398 return EINA_TRUE; 1432 return EINA_TRUE;
1399 } 1433 }
1400 } 1434 }
diff --git a/src/lib/evas/canvas/evas_callbacks.c b/src/lib/evas/canvas/evas_callbacks.c
index 4f63c2323d..8896dea691 100644
--- a/src/lib/evas/canvas/evas_callbacks.c
+++ b/src/lib/evas/canvas/evas_callbacks.c
@@ -700,7 +700,7 @@ _animator_repeater(void *data, const Efl_Event *event)
700static void 700static void
701_check_event_catcher_add(void *data, const Efl_Event *event) 701_check_event_catcher_add(void *data, const Efl_Event *event)
702{ 702{
703 const Efl_Callback_Array_Item *array = event->info; 703 const Efl_Callback_Array_Item_Full *array = event->info;
704 Evas_Object_Protected_Data *obj = data; 704 Evas_Object_Protected_Data *obj = data;
705 Evas_Callback_Type type = EVAS_CALLBACK_LAST; 705 Evas_Callback_Type type = EVAS_CALLBACK_LAST;
706 int i; 706 int i;
@@ -728,7 +728,7 @@ _check_event_catcher_add(void *data, const Efl_Event *event)
728static void 728static void
729_check_event_catcher_del(void *data, const Efl_Event *event) 729_check_event_catcher_del(void *data, const Efl_Event *event)
730{ 730{
731 const Efl_Callback_Array_Item *array = event->info; 731 const Efl_Callback_Array_Item_Full *array = event->info;
732 Evas_Object_Protected_Data *obj = data; 732 Evas_Object_Protected_Data *obj = data;
733 int i; 733 int i;
734 734
diff --git a/src/tests/ecore/ecore_test_ecore.c b/src/tests/ecore/ecore_test_ecore.c
index 492c2aa033..6fd95738f4 100644
--- a/src/tests/ecore/ecore_test_ecore.c
+++ b/src/tests/ecore/ecore_test_ecore.c
@@ -896,11 +896,11 @@ START_TEST(ecore_test_efl_app_version)
896 896
897 ecore_init(); 897 ecore_init();
898 898
899 loop = efl_loop_main_get(EFL_LOOP_CLASS); 899 loop = efl_app_loop_main_get(EFL_APP_CLASS);
900 fail_if(!efl_isa(loop, EFL_LOOP_CLASS)); 900 fail_if(!efl_isa(loop, EFL_LOOP_CLASS));
901 901
902 efl_build_version_set(EFL_VERSION_MAJOR, EFL_VERSION_MINOR, 0, 0, NULL, EFL_BUILD_ID); 902 efl_build_version_set(EFL_VERSION_MAJOR, EFL_VERSION_MINOR, 0, 0, NULL, EFL_BUILD_ID);
903 ver = efl_loop_app_efl_version_get(loop); 903 ver = efl_app_build_efl_version_get(loop);
904 fail_if(!ver); 904 fail_if(!ver);
905 fail_if(ver->major != EFL_VERSION_MAJOR); 905 fail_if(ver->major != EFL_VERSION_MAJOR);
906 fail_if(ver->minor != EFL_VERSION_MINOR); 906 fail_if(ver->minor != EFL_VERSION_MINOR);
@@ -909,7 +909,7 @@ START_TEST(ecore_test_efl_app_version)
909 fail_if(ver->flavor); 909 fail_if(ver->flavor);
910 fail_if(!eina_streq(ver->build_id, EFL_BUILD_ID)); 910 fail_if(!eina_streq(ver->build_id, EFL_BUILD_ID));
911 911
912 ver = efl_loop_efl_version_get(loop); 912 ver = efl_app_efl_version_get(loop);
913 fail_if(!ver); 913 fail_if(!ver);
914 fail_if(ver->major != EFL_VERSION_MAJOR); 914 fail_if(ver->major != EFL_VERSION_MAJOR);
915 fail_if(ver->minor != EFL_VERSION_MINOR); 915 fail_if(ver->minor != EFL_VERSION_MINOR);
diff --git a/src/tests/elementary/efl_ui_suite.c b/src/tests/elementary/efl_ui_suite.c
index 629bb10faa..d2269b68a7 100644
--- a/src/tests/elementary/efl_ui_suite.c
+++ b/src/tests/elementary/efl_ui_suite.c
@@ -32,10 +32,10 @@ START_TEST(efl_ui_test_init)
32 _efl_startup_time = ecore_time_unix_get(); 32 _efl_startup_time = ecore_time_unix_get();
33 _EFL_APP_VERSION_SET(); 33 _EFL_APP_VERSION_SET();
34 fail_if(!ecore_init()); 34 fail_if(!ecore_init());
35 efl_event_callback_add(efl_app_main_loop_get(efl_app_get()), EFL_LOOP_EVENT_ARGUMENTS, efl_main, NULL); 35 efl_event_callback_add(efl_app_get(), EFL_LOOP_EVENT_ARGUMENTS, efl_main, NULL);
36 fail_if(!ecore_init_ex(argc, argv)); 36 fail_if(!ecore_init_ex(argc, argv));
37 __EFL_MAIN_CONSTRUCTOR; 37 __EFL_MAIN_CONSTRUCTOR;
38 ret__ = efl_loop_begin(efl_app_main_loop_get(efl_app_get())); 38 ret__ = efl_loop_begin(efl_app_get());
39 real__ = efl_loop_exit_code_process(ret__); 39 real__ = efl_loop_exit_code_process(ret__);
40 __EFL_MAIN_DESTRUCTOR; 40 __EFL_MAIN_DESTRUCTOR;
41 ecore_shutdown_ex(); 41 ecore_shutdown_ex();
diff --git a/src/tests/eo/signals/signals_simple.c b/src/tests/eo/signals/signals_simple.c
index 9449c3f8c0..0e016dc550 100644
--- a/src/tests/eo/signals/signals_simple.c
+++ b/src/tests/eo/signals/signals_simple.c
@@ -32,7 +32,7 @@ void
32_cb_added(void *data EINA_UNUSED, const Efl_Event *event) 32_cb_added(void *data EINA_UNUSED, const Efl_Event *event)
33{ 33{
34 Simple_Public_Data *pd = efl_data_scope_get(event->object, MY_CLASS); 34 Simple_Public_Data *pd = efl_data_scope_get(event->object, MY_CLASS);
35 const Efl_Callback_Array_Item *callback_array = event->info; 35 const Efl_Callback_Array_Item_Full *callback_array = event->info;
36 36
37 if (callback_array->desc != EV_A_CHANGED) 37 if (callback_array->desc != EV_A_CHANGED)
38 return; 38 return;
@@ -46,7 +46,7 @@ void
46_cb_deled(void *data EINA_UNUSED, const Efl_Event *event) 46_cb_deled(void *data EINA_UNUSED, const Efl_Event *event)
47{ 47{
48 Simple_Public_Data *pd = efl_data_scope_get(event->object, MY_CLASS); 48 Simple_Public_Data *pd = efl_data_scope_get(event->object, MY_CLASS);
49 const Efl_Callback_Array_Item *callback_array = event->info; 49 const Efl_Callback_Array_Item_Full *callback_array = event->info;
50 50
51 if (callback_array->desc != EV_A_CHANGED) 51 if (callback_array->desc != EV_A_CHANGED)
52 return; 52 return;
diff --git a/src/tests/eo/suite/eo_test_general.c b/src/tests/eo/suite/eo_test_general.c
index e475889e95..18684f1ad2 100644
--- a/src/tests/eo/suite/eo_test_general.c
+++ b/src/tests/eo/suite/eo_test_general.c
@@ -181,11 +181,9 @@ _eo_signals_efl_del_cb(void *_data EINA_UNUSED, const Efl_Event *event EINA_UNUS
181void 181void
182_eo_signals_cb_added_deled(void *data, const Efl_Event *event) 182_eo_signals_cb_added_deled(void *data, const Efl_Event *event)
183{ 183{
184 const Efl_Callback_Array_Item *callback_array = event->info; 184 const Efl_Callback_Array_Item_Full *callback_array = event->info;
185 const Efl_Callback_Array_Item *(*callback_data)(void) = data;
186 185
187 fail_if((callback_data() != callback_array) && 186 fail_if(callback_array->func != _eo_signals_cb_added_deled);
188 (callback_array->func != _eo_signals_cb_added_deled));
189} 187}
190 188
191EFL_CALLBACKS_ARRAY_DEFINE(_eo_signals_callbacks, 189EFL_CALLBACKS_ARRAY_DEFINE(_eo_signals_callbacks,