2018-02-27 04:19:17 -08:00
|
|
|
#ifdef HAVE_CONFIG_H
|
|
|
|
# include <config.h>
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#define EFL_IO_READER_PROTECTED 1
|
|
|
|
#define EFL_IO_WRITER_PROTECTED 1
|
|
|
|
#define EFL_IO_CLOSER_PROTECTED 1
|
|
|
|
|
2019-05-17 03:52:41 -07:00
|
|
|
#ifdef _WIN32
|
|
|
|
# include <evil_private.h> /* pipe fcntl */
|
|
|
|
#endif
|
2018-02-27 04:19:17 -08:00
|
|
|
#include <Ecore.h>
|
|
|
|
|
|
|
|
#include "ecore_private.h"
|
|
|
|
|
|
|
|
#include <unistd.h>
|
|
|
|
#include <fcntl.h>
|
|
|
|
#include <string.h>
|
|
|
|
|
|
|
|
#define MY_CLASS EFL_THREAD_CLASS
|
|
|
|
|
2018-03-06 03:49:51 -08:00
|
|
|
#define APPTHREAD_CLASS EFL_APPTHREAD_CLASS
|
|
|
|
|
2018-02-27 04:19:17 -08:00
|
|
|
typedef struct
|
|
|
|
{
|
|
|
|
const char *name;
|
|
|
|
struct {
|
|
|
|
int in, out;
|
|
|
|
Eo *in_handler, *out_handler;
|
|
|
|
} fd, ctrl;
|
Revert "Revert command line array object because it's broken by design"
This reverts commit a57c7f751023fe1d1edeabbf8683574ac7497e5e.
I pretty much hate to just revert your revert, but you failed to read my
replies, and failed to understand what i was talking about.
And YES we talked at fosdem about the platform issue, and do you
remember my answer, that back in time this might be the case, today is
different freebsd suppoerts setenv, and for windows we have a setenv
implementation in evil. And yes, vtorri also created a issue how bad and
evil this commit is, however, i still fail to see the issue since setenv
unsetenv and clearenv usages are taken as needed. (T7693)
The ownership question is answered in
https://phab.enlightenment.org/D7516#137367.
Can we please get into a state of technical discussions, and not *oh
shit, i am going to revert this* this has been in review for a long
time, a lots of people have tested it, we discussed things on it, and
there was 3 weeks of no reply from you.
The issues that exist will be dealed with. Feel free to create tasks if
you want :)
2019-02-12 12:34:30 -08:00
|
|
|
Eina_Array *argv;
|
2018-02-27 04:19:17 -08:00
|
|
|
Efl_Callback_Array_Item_Full *event_cb;
|
2018-03-06 03:49:51 -08:00
|
|
|
void *indata, *outdata;
|
2018-02-27 04:19:17 -08:00
|
|
|
} Thread_Data;
|
|
|
|
|
2018-03-06 03:49:51 -08:00
|
|
|
#define CMD_EXIT 1
|
|
|
|
#define CMD_EXITED 2
|
|
|
|
#define CMD_CALL 3
|
|
|
|
#define CMD_CALL_SYNC 4
|
2018-02-27 04:19:17 -08:00
|
|
|
|
|
|
|
typedef struct
|
|
|
|
{
|
2018-03-06 03:49:51 -08:00
|
|
|
Eina_Semaphore sem;
|
|
|
|
void *data;
|
|
|
|
} Control_Reply;
|
|
|
|
|
|
|
|
typedef struct
|
|
|
|
{
|
|
|
|
union {
|
|
|
|
struct {
|
|
|
|
int command;
|
|
|
|
int data;
|
|
|
|
void *ptr[4];
|
|
|
|
} d;
|
|
|
|
unsigned char b[64];
|
|
|
|
};
|
2018-02-27 04:19:17 -08:00
|
|
|
} Control_Data;
|
|
|
|
|
|
|
|
typedef struct _Efl_Thread_Data Efl_Thread_Data;
|
|
|
|
|
|
|
|
struct _Efl_Thread_Data
|
|
|
|
{
|
|
|
|
struct {
|
|
|
|
int in, out;
|
|
|
|
Eo *in_handler, *out_handler;
|
|
|
|
Eina_Bool can_read : 1;
|
|
|
|
Eina_Bool eos_read : 1;
|
|
|
|
Eina_Bool can_write : 1;
|
|
|
|
} fd, ctrl;
|
|
|
|
int read_listeners;
|
|
|
|
Eo *loop;
|
|
|
|
Thread_Data *thdat;
|
|
|
|
Efl_Callback_Array_Item_Full *event_cb;
|
|
|
|
Eina_Thread thread;
|
|
|
|
Eina_Bool end_sent : 1;
|
|
|
|
Eina_Bool exit_read : 1;
|
|
|
|
Eina_Bool exit_called : 1;
|
2018-03-10 03:02:09 -08:00
|
|
|
Eina_Bool run : 1;
|
2018-02-27 04:19:17 -08:00
|
|
|
};
|
|
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
static void
|
|
|
|
_cb_thread_out(void *data, const Efl_Event *event EINA_UNUSED)
|
|
|
|
{
|
|
|
|
Eo *obj = data;
|
|
|
|
efl_io_reader_can_read_set(obj, EINA_TRUE);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
_cb_thread_in(void *data, const Efl_Event *event EINA_UNUSED)
|
|
|
|
{
|
|
|
|
Eo *obj = data;
|
|
|
|
efl_io_writer_can_write_set(obj, EINA_TRUE);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
_cb_thread_ctrl_out(void *data, const Efl_Event *event EINA_UNUSED)
|
|
|
|
{
|
|
|
|
Eo *obj = data;
|
|
|
|
Control_Data cmd;
|
|
|
|
ssize_t ret;
|
|
|
|
Efl_Appthread_Data *ad;
|
|
|
|
|
2018-03-06 03:49:51 -08:00
|
|
|
ad = efl_data_scope_get(obj, APPTHREAD_CLASS);
|
|
|
|
memset(&cmd, 0, sizeof(cmd));
|
2018-02-27 04:19:17 -08:00
|
|
|
ret = read(ad->ctrl.out, &cmd, sizeof(Control_Data));
|
|
|
|
if (ret == sizeof(Control_Data))
|
|
|
|
{
|
2018-03-06 03:49:51 -08:00
|
|
|
if (cmd.d.command == CMD_EXIT)
|
2018-02-27 04:19:17 -08:00
|
|
|
{
|
2018-03-20 04:43:47 -07:00
|
|
|
efl_event_callback_call(obj, EFL_LOOP_EVENT_QUIT, NULL);
|
2018-02-27 04:19:17 -08:00
|
|
|
efl_loop_quit(obj, eina_value_int_init(0));
|
|
|
|
}
|
2018-03-06 03:49:51 -08:00
|
|
|
else if (cmd.d.command == CMD_CALL)
|
|
|
|
{
|
2019-07-30 06:36:32 -07:00
|
|
|
EflThreadIOCall func = cmd.d.ptr[0];
|
2018-03-06 03:49:51 -08:00
|
|
|
void *data = cmd.d.ptr[1];
|
|
|
|
Eina_Free_Cb free_func = cmd.d.ptr[2];
|
2018-04-04 03:35:19 -07:00
|
|
|
if (func)
|
|
|
|
{
|
2019-08-08 14:18:45 -07:00
|
|
|
Efl_Event ev = { obj, NULL, NULL };
|
2018-04-04 03:35:19 -07:00
|
|
|
|
2019-08-08 14:18:45 -07:00
|
|
|
func(data, &ev);
|
2018-04-04 03:35:19 -07:00
|
|
|
}
|
2018-03-06 03:49:51 -08:00
|
|
|
if (free_func) free_func(data);
|
|
|
|
}
|
|
|
|
else if (cmd.d.command == CMD_CALL_SYNC)
|
|
|
|
{
|
2019-07-30 06:36:32 -07:00
|
|
|
EflThreadIOCallSync func = cmd.d.ptr[0];
|
2019-08-08 14:18:45 -07:00
|
|
|
void *d = cmd.d.ptr[1];
|
2018-03-06 03:49:51 -08:00
|
|
|
Eina_Free_Cb free_func = cmd.d.ptr[2];
|
|
|
|
Control_Reply *rep = cmd.d.ptr[3];
|
2018-04-04 03:35:19 -07:00
|
|
|
if (func)
|
|
|
|
{
|
2019-08-08 14:18:45 -07:00
|
|
|
Efl_Event ev = { obj, NULL, NULL };
|
2018-04-04 03:35:19 -07:00
|
|
|
|
2019-08-08 14:18:45 -07:00
|
|
|
rep->data = func(d, &ev);
|
2018-04-04 03:35:19 -07:00
|
|
|
}
|
2019-08-08 14:18:45 -07:00
|
|
|
if (free_func) free_func(d);
|
2018-03-06 03:49:51 -08:00
|
|
|
eina_semaphore_release(&(rep->sem), 1);
|
|
|
|
}
|
2018-02-27 04:19:17 -08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static Eina_Value
|
2018-12-07 03:29:22 -08:00
|
|
|
_efl_loop_arguments_send(Eo *obj, void *data EINA_UNUSED, const Eina_Value v)
|
2018-02-27 04:19:17 -08:00
|
|
|
|
|
|
|
{
|
|
|
|
Efl_Loop_Arguments arge;
|
|
|
|
Eina_Array *arga;
|
|
|
|
Eina_Stringshare *s;
|
Revert "Revert command line array object because it's broken by design"
This reverts commit a57c7f751023fe1d1edeabbf8683574ac7497e5e.
I pretty much hate to just revert your revert, but you failed to read my
replies, and failed to understand what i was talking about.
And YES we talked at fosdem about the platform issue, and do you
remember my answer, that back in time this might be the case, today is
different freebsd suppoerts setenv, and for windows we have a setenv
implementation in evil. And yes, vtorri also created a issue how bad and
evil this commit is, however, i still fail to see the issue since setenv
unsetenv and clearenv usages are taken as needed. (T7693)
The ownership question is answered in
https://phab.enlightenment.org/D7516#137367.
Can we please get into a state of technical discussions, and not *oh
shit, i am going to revert this* this has been in review for a long
time, a lots of people have tested it, we discussed things on it, and
there was 3 weeks of no reply from you.
The issues that exist will be dealed with. Feel free to create tasks if
you want :)
2019-02-12 12:34:30 -08:00
|
|
|
Eina_Accessor *accessor;
|
|
|
|
const char *argv;
|
|
|
|
int i = 0;
|
2018-02-27 04:19:17 -08:00
|
|
|
|
Revert "Revert command line array object because it's broken by design"
This reverts commit a57c7f751023fe1d1edeabbf8683574ac7497e5e.
I pretty much hate to just revert your revert, but you failed to read my
replies, and failed to understand what i was talking about.
And YES we talked at fosdem about the platform issue, and do you
remember my answer, that back in time this might be the case, today is
different freebsd suppoerts setenv, and for windows we have a setenv
implementation in evil. And yes, vtorri also created a issue how bad and
evil this commit is, however, i still fail to see the issue since setenv
unsetenv and clearenv usages are taken as needed. (T7693)
The ownership question is answered in
https://phab.enlightenment.org/D7516#137367.
Can we please get into a state of technical discussions, and not *oh
shit, i am going to revert this* this has been in review for a long
time, a lots of people have tested it, we discussed things on it, and
there was 3 weeks of no reply from you.
The issues that exist will be dealed with. Feel free to create tasks if
you want :)
2019-02-12 12:34:30 -08:00
|
|
|
accessor = efl_core_command_line_command_access(obj);
|
2019-02-14 17:16:49 -08:00
|
|
|
if (accessor)
|
2018-02-27 04:19:17 -08:00
|
|
|
{
|
2019-02-14 17:16:49 -08:00
|
|
|
arga = eina_array_new(10);
|
|
|
|
|
|
|
|
EINA_ACCESSOR_FOREACH(accessor, i, argv)
|
|
|
|
{
|
|
|
|
eina_array_push(arga, eina_stringshare_add(argv));
|
|
|
|
}
|
|
|
|
arge.argv = arga;
|
2018-02-27 04:19:17 -08:00
|
|
|
}
|
2019-02-14 17:16:49 -08:00
|
|
|
else arge.argv = NULL;
|
2018-02-27 04:19:17 -08:00
|
|
|
arge.initialization = EINA_TRUE;
|
|
|
|
efl_event_callback_call(obj,
|
|
|
|
EFL_LOOP_EVENT_ARGUMENTS, &arge);
|
2019-02-14 17:16:49 -08:00
|
|
|
if (accessor)
|
|
|
|
{
|
|
|
|
while ((s = eina_array_pop(arga))) eina_stringshare_del(s);
|
|
|
|
eina_array_free(arga);
|
|
|
|
eina_accessor_free(accessor);
|
|
|
|
}
|
2018-12-07 03:29:22 -08:00
|
|
|
|
2018-02-27 04:19:17 -08:00
|
|
|
return v;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
_appthread_parent_read_listeners_modify(Efl_Appthread_Data *ad, int mod)
|
|
|
|
{
|
|
|
|
ad->read_listeners += mod;
|
|
|
|
|
|
|
|
if (ad->fd.out_handler)
|
|
|
|
{
|
|
|
|
if ((ad->read_listeners == 0) && (mod < 0))
|
|
|
|
efl_loop_handler_active_set
|
|
|
|
(ad->fd.out_handler, EFL_LOOP_HANDLER_FLAGS_NONE);
|
|
|
|
else if ((ad->read_listeners == 1) && (mod > 0))
|
|
|
|
efl_loop_handler_active_set
|
|
|
|
(ad->fd.out_handler, EFL_LOOP_HANDLER_FLAGS_READ);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
_cb_appthread_event_callback_add(void *data, const Efl_Event *event)
|
|
|
|
{
|
|
|
|
Efl_Appthread_Data *ad = data;
|
|
|
|
const Efl_Callback_Array_Item_Full *array = event->info;
|
|
|
|
int i;
|
|
|
|
|
|
|
|
for (i = 0; array[i].desc != NULL; i++)
|
|
|
|
{
|
|
|
|
if (array[i].desc == EFL_IO_READER_EVENT_CAN_READ_CHANGED)
|
|
|
|
_appthread_parent_read_listeners_modify(ad, 1);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
_cb_appthread_event_callback_del(void *data, const Efl_Event *event)
|
|
|
|
{
|
|
|
|
Efl_Appthread_Data *ad = data;
|
|
|
|
const Efl_Callback_Array_Item_Full *array = event->info;
|
|
|
|
int i;
|
|
|
|
|
|
|
|
for (i = 0; array[i].desc != NULL; i++)
|
|
|
|
{
|
|
|
|
if (array[i].desc == EFL_IO_READER_EVENT_CAN_READ_CHANGED)
|
|
|
|
_appthread_parent_read_listeners_modify(ad, -1);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-06-20 03:24:57 -07:00
|
|
|
static void
|
|
|
|
_efl_thread_pipe_write(int fd, const void *buf, size_t count)
|
|
|
|
{
|
|
|
|
const char *my_buf = buf;
|
|
|
|
ssize_t ret;
|
|
|
|
|
|
|
|
for (;;)
|
|
|
|
{
|
|
|
|
ret = write(fd, my_buf, count);
|
|
|
|
if (ret < 0)
|
|
|
|
{
|
|
|
|
// try again tyope errors
|
|
|
|
if (errno == EINTR) continue;
|
|
|
|
else if (errno == EAGAIN) continue;
|
|
|
|
// bad errors - fatal for this kind of write
|
|
|
|
else if (errno == EBADF)
|
|
|
|
ERR("Error writing to control pipe fd: Bad fd");
|
|
|
|
else if (errno == EFAULT)
|
|
|
|
ERR("Error writing to control pipe fd: Bad buf outside address space");
|
|
|
|
else if (errno == EINVAL)
|
|
|
|
ERR("Error writing to control pipe fd: Invalid value");
|
|
|
|
else if (errno == EPIPE)
|
|
|
|
ERR("Error writing to control pipe fd: Broken Pipe");
|
|
|
|
else
|
|
|
|
ERR("Error writing to control pipe fd: Something else unexpected");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
// do it in multiple writes then if only part was written
|
|
|
|
else if (ret >= 0)
|
|
|
|
{
|
|
|
|
my_buf += ret;
|
|
|
|
count -= ret;
|
|
|
|
if (count == 0) return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-02-27 04:19:17 -08:00
|
|
|
EFL_CALLBACKS_ARRAY_DEFINE(_appthread_event_callback_watch,
|
|
|
|
{ EFL_EVENT_CALLBACK_ADD, _cb_appthread_event_callback_add },
|
|
|
|
{ EFL_EVENT_CALLBACK_DEL, _cb_appthread_event_callback_del });
|
|
|
|
|
|
|
|
static void *
|
|
|
|
_efl_thread_main(void *data, Eina_Thread t)
|
|
|
|
{
|
|
|
|
Efl_Appthread_Data *ad;
|
|
|
|
Thread_Data *thdat = data;
|
|
|
|
Eo *obj;
|
|
|
|
Eina_Value *ret;
|
|
|
|
Control_Data cmd;
|
|
|
|
int real;
|
|
|
|
Efl_Callback_Array_Item_Full *it;
|
|
|
|
|
|
|
|
if (thdat->name) eina_thread_name_set(t, thdat->name);
|
|
|
|
else eina_thread_name_set(t, "Eflthread");
|
|
|
|
|
2018-03-15 09:50:20 -07:00
|
|
|
obj = efl_add_ref(APPTHREAD_CLASS, NULL);
|
2018-03-06 03:49:51 -08:00
|
|
|
ad = efl_data_scope_get(obj, APPTHREAD_CLASS);
|
|
|
|
efl_threadio_indata_set(obj, thdat->indata);
|
|
|
|
efl_threadio_outdata_set(obj, thdat->outdata);
|
2018-02-27 04:19:17 -08:00
|
|
|
efl_event_callback_array_add(obj, _appthread_event_callback_watch(), ad);
|
|
|
|
|
|
|
|
// add handlers for "stdio"
|
|
|
|
thdat->fd.in_handler =
|
|
|
|
efl_add(EFL_LOOP_HANDLER_CLASS, obj,
|
|
|
|
efl_loop_handler_fd_set(efl_added, thdat->fd.in),
|
|
|
|
efl_event_callback_add
|
|
|
|
(efl_added, EFL_LOOP_HANDLER_EVENT_WRITE, _cb_thread_in, obj));
|
|
|
|
thdat->fd.out_handler =
|
|
|
|
efl_add(EFL_LOOP_HANDLER_CLASS, obj,
|
|
|
|
efl_loop_handler_fd_set(efl_added, thdat->fd.out),
|
|
|
|
efl_event_callback_add
|
|
|
|
(efl_added, EFL_LOOP_HANDLER_EVENT_READ, _cb_thread_out, obj));
|
|
|
|
// add handlers for control pipes
|
|
|
|
thdat->ctrl.in_handler =
|
|
|
|
efl_add(EFL_LOOP_HANDLER_CLASS, obj,
|
|
|
|
efl_loop_handler_fd_set(efl_added, thdat->ctrl.in));
|
|
|
|
thdat->ctrl.out_handler =
|
|
|
|
efl_add(EFL_LOOP_HANDLER_CLASS, obj,
|
|
|
|
efl_loop_handler_fd_set(efl_added, thdat->ctrl.out),
|
|
|
|
efl_event_callback_add
|
|
|
|
(efl_added, EFL_LOOP_HANDLER_EVENT_READ, _cb_thread_ctrl_out, obj),
|
|
|
|
efl_loop_handler_active_set
|
|
|
|
(efl_added, EFL_LOOP_HANDLER_FLAGS_READ));
|
|
|
|
ad->fd.in = thdat->fd.in;
|
|
|
|
ad->fd.out = thdat->fd.out;
|
|
|
|
ad->ctrl.in = thdat->ctrl.in;
|
|
|
|
ad->ctrl.out = thdat->ctrl.out;
|
|
|
|
ad->fd.in_handler = thdat->fd.in_handler;
|
|
|
|
ad->fd.out_handler = thdat->fd.out_handler;
|
|
|
|
ad->ctrl.in_handler = thdat->ctrl.in_handler;
|
|
|
|
ad->ctrl.out_handler = thdat->ctrl.out_handler;
|
2018-03-06 03:49:51 -08:00
|
|
|
ad->thdat = thdat;
|
2018-02-27 04:19:17 -08:00
|
|
|
|
|
|
|
if (thdat->event_cb)
|
|
|
|
{
|
|
|
|
for (it = thdat->event_cb; it->func; it++)
|
|
|
|
efl_event_callback_priority_add(obj, it->desc, it->priority,
|
|
|
|
it->func, it->user_data);
|
|
|
|
}
|
2019-02-14 17:16:49 -08:00
|
|
|
if (thdat->argv) efl_core_command_line_command_array_set(obj, thdat->argv);
|
2019-02-14 03:28:23 -08:00
|
|
|
thdat->argv = NULL;
|
2018-12-07 03:29:22 -08:00
|
|
|
efl_future_then(obj, efl_loop_job(obj),
|
|
|
|
.success = _efl_loop_arguments_send);
|
2018-02-27 04:19:17 -08:00
|
|
|
free(thdat->event_cb);
|
|
|
|
thdat->event_cb = NULL;
|
|
|
|
|
|
|
|
ret = efl_loop_begin(obj);
|
|
|
|
real = efl_loop_exit_code_process(ret);
|
2018-03-06 03:49:51 -08:00
|
|
|
thdat->outdata = efl_threadio_outdata_get(obj);
|
2018-02-27 04:19:17 -08:00
|
|
|
|
2018-03-06 03:49:51 -08:00
|
|
|
memset(&cmd, 0, sizeof(cmd));
|
|
|
|
cmd.d.command = CMD_EXITED;
|
|
|
|
cmd.d.data = real;
|
2019-06-20 03:24:57 -07:00
|
|
|
_efl_thread_pipe_write(thdat->ctrl.in, &cmd, sizeof(Control_Data));
|
2018-02-27 04:19:17 -08:00
|
|
|
|
2018-03-15 09:50:20 -07:00
|
|
|
efl_unref(obj);
|
2018-02-27 04:19:17 -08:00
|
|
|
|
|
|
|
thdat->fd.in_handler = NULL;
|
|
|
|
thdat->fd.out_handler = NULL;
|
|
|
|
thdat->ctrl.in_handler = NULL;
|
|
|
|
thdat->ctrl.out_handler = NULL;
|
|
|
|
thdat->fd.in = -1;
|
|
|
|
thdat->fd.out = -1;
|
|
|
|
thdat->ctrl.in = -1;
|
|
|
|
thdat->ctrl.out = -1;
|
|
|
|
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
static void
|
|
|
|
_thread_exit_eval(Eo *obj, Efl_Thread_Data *pd)
|
|
|
|
{
|
|
|
|
if ((pd->fd.out == -1) && /*(pd->fd.in == -1) &&*/
|
|
|
|
(pd->exit_read) && (!pd->exit_called))
|
|
|
|
{
|
|
|
|
pd->exit_called = EINA_TRUE;
|
2018-03-06 03:49:51 -08:00
|
|
|
if (pd->thdat) efl_threadio_outdata_set(obj, pd->thdat->outdata);
|
2019-09-10 15:01:19 -07:00
|
|
|
efl_event_callback_call(obj, EFL_TASK_EVENT_EXIT, NULL);
|
2019-08-26 05:46:32 -07:00
|
|
|
efl_del(obj);
|
2018-02-27 04:19:17 -08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
_cb_thread_parent_out(void *data, const Efl_Event *event EINA_UNUSED)
|
|
|
|
{
|
|
|
|
Eo *obj = data;
|
|
|
|
efl_io_reader_can_read_set(obj, EINA_TRUE);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
_cb_thread_parent_in(void *data, const Efl_Event *event EINA_UNUSED)
|
|
|
|
{
|
|
|
|
Eo *obj = data;
|
|
|
|
efl_io_writer_can_write_set(obj, EINA_TRUE);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
_cb_thread_parent_ctrl_out(void *data, const Efl_Event *event EINA_UNUSED)
|
|
|
|
{
|
|
|
|
Eo *obj = data;
|
|
|
|
Control_Data cmd;
|
|
|
|
ssize_t ret;
|
|
|
|
Efl_Thread_Data *pd = efl_data_scope_get(obj, MY_CLASS);
|
|
|
|
|
|
|
|
if (!pd) return;
|
|
|
|
|
2018-03-06 03:49:51 -08:00
|
|
|
memset(&cmd, 0, sizeof(cmd));
|
2018-02-27 04:19:17 -08:00
|
|
|
ret = read(pd->ctrl.out, &cmd, sizeof(Control_Data));
|
|
|
|
if (ret == sizeof(Control_Data))
|
|
|
|
{
|
2018-03-06 03:49:51 -08:00
|
|
|
if (cmd.d.command == CMD_EXITED)
|
2018-02-27 04:19:17 -08:00
|
|
|
{
|
|
|
|
if (!pd->exit_read)
|
|
|
|
{
|
|
|
|
Efl_Task_Data *td = efl_data_scope_get(obj, EFL_TASK_CLASS);
|
|
|
|
|
2018-03-06 03:49:51 -08:00
|
|
|
if (td) td->exit_code = cmd.d.data;
|
2018-02-27 04:19:17 -08:00
|
|
|
pd->exit_read = EINA_TRUE;
|
|
|
|
_thread_exit_eval(obj, pd);
|
|
|
|
}
|
|
|
|
}
|
2018-03-06 03:49:51 -08:00
|
|
|
else if (cmd.d.command == CMD_CALL)
|
|
|
|
{
|
2019-07-30 06:36:32 -07:00
|
|
|
EflThreadIOCall func = cmd.d.ptr[0];
|
2018-03-06 03:49:51 -08:00
|
|
|
void *data = cmd.d.ptr[1];
|
|
|
|
Eina_Free_Cb free_func = cmd.d.ptr[2];
|
2018-04-04 03:35:19 -07:00
|
|
|
if (func)
|
|
|
|
{
|
|
|
|
Efl_Event event = { obj, NULL, NULL };
|
|
|
|
|
|
|
|
func(data, &event);
|
|
|
|
}
|
2018-03-06 03:49:51 -08:00
|
|
|
if (free_func) free_func(data);
|
|
|
|
}
|
|
|
|
else if (cmd.d.command == CMD_CALL_SYNC)
|
|
|
|
{
|
2019-07-30 06:36:32 -07:00
|
|
|
EflThreadIOCallSync func = cmd.d.ptr[0];
|
2018-03-06 03:49:51 -08:00
|
|
|
void *data = cmd.d.ptr[1];
|
|
|
|
Eina_Free_Cb free_func = cmd.d.ptr[2];
|
|
|
|
Control_Reply *rep = cmd.d.ptr[3];
|
2018-04-04 03:35:19 -07:00
|
|
|
if (func)
|
|
|
|
{
|
|
|
|
Efl_Event event = { obj, NULL, NULL };
|
|
|
|
|
|
|
|
rep->data = func(data, &event);
|
|
|
|
}
|
2018-03-06 03:49:51 -08:00
|
|
|
if (free_func) free_func(data);
|
|
|
|
eina_semaphore_release(&(rep->sem), 1);
|
|
|
|
}
|
2018-02-27 04:19:17 -08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
static void
|
|
|
|
_thread_parent_read_listeners_modify(Efl_Thread_Data *pd, int mod)
|
|
|
|
{
|
|
|
|
pd->read_listeners += mod;
|
|
|
|
|
|
|
|
if (pd->fd.out_handler)
|
|
|
|
{
|
|
|
|
if ((pd->read_listeners == 0) && (mod < 0))
|
|
|
|
efl_loop_handler_active_set
|
|
|
|
(pd->fd.out_handler, EFL_LOOP_HANDLER_FLAGS_NONE);
|
|
|
|
else if ((pd->read_listeners == 1) && (mod > 0))
|
|
|
|
efl_loop_handler_active_set
|
|
|
|
(pd->fd.out_handler, EFL_LOOP_HANDLER_FLAGS_READ);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
_cb_event_callback_add(void *data, const Efl_Event *event)
|
|
|
|
{
|
|
|
|
Efl_Thread_Data *pd = data;
|
|
|
|
const Efl_Callback_Array_Item_Full *array = event->info;
|
|
|
|
int i;
|
|
|
|
|
|
|
|
for (i = 0; array[i].desc != NULL; i++)
|
|
|
|
{
|
|
|
|
if (array[i].desc == EFL_LOOP_EVENT_ARGUMENTS)
|
|
|
|
{
|
|
|
|
Efl_Callback_Array_Item_Full *event_cb, *it;
|
|
|
|
int num;
|
|
|
|
|
|
|
|
num = 0;
|
|
|
|
if (pd->event_cb)
|
|
|
|
{
|
|
|
|
for (it = pd->event_cb; it->func; it++) num++;
|
|
|
|
}
|
|
|
|
num++;
|
|
|
|
event_cb = realloc(pd->event_cb, (num + 1) * sizeof(Efl_Callback_Array_Item_Full));
|
|
|
|
if (event_cb)
|
|
|
|
{
|
|
|
|
pd->event_cb = event_cb;
|
|
|
|
event_cb[num - 1] = array[i];
|
|
|
|
event_cb[num].desc = NULL;
|
|
|
|
event_cb[num].priority = 0;
|
|
|
|
event_cb[num].func = NULL;
|
|
|
|
event_cb[num].user_data = NULL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (array[i].desc == EFL_IO_READER_EVENT_CAN_READ_CHANGED)
|
|
|
|
_thread_parent_read_listeners_modify(pd, 1);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
_cb_event_callback_del(void *data, const Efl_Event *event)
|
|
|
|
{
|
|
|
|
Efl_Thread_Data *pd = data;
|
|
|
|
const Efl_Callback_Array_Item_Full *array = event->info;
|
|
|
|
int i;
|
|
|
|
|
|
|
|
for (i = 0; array[i].desc != NULL; i++)
|
|
|
|
{
|
|
|
|
if (array[i].desc == EFL_LOOP_EVENT_ARGUMENTS)
|
|
|
|
{
|
|
|
|
Efl_Callback_Array_Item_Full *it;
|
|
|
|
|
|
|
|
if (pd->event_cb)
|
|
|
|
{
|
|
|
|
Eina_Bool shuffle_down = EINA_FALSE;
|
|
|
|
|
|
|
|
for (it = pd->event_cb; it->func; it++)
|
|
|
|
{
|
|
|
|
if ((it->desc == array[i].desc) &&
|
|
|
|
(it->priority == array[i].priority) &&
|
|
|
|
(it->func == array[i].func) &&
|
|
|
|
(it->user_data == array[i].user_data))
|
|
|
|
shuffle_down = EINA_TRUE;
|
|
|
|
if (shuffle_down) it[0] = it[1];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (array[i].desc == EFL_IO_READER_EVENT_CAN_READ_CHANGED)
|
|
|
|
_thread_parent_read_listeners_modify(pd, -1);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
EFL_CALLBACKS_ARRAY_DEFINE(_event_callback_watch,
|
|
|
|
{ EFL_EVENT_CALLBACK_ADD, _cb_event_callback_add },
|
|
|
|
{ EFL_EVENT_CALLBACK_DEL, _cb_event_callback_del });
|
|
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
EOLIAN static Efl_Object *
|
|
|
|
_efl_thread_efl_object_constructor(Eo *obj, Efl_Thread_Data *pd)
|
|
|
|
{
|
|
|
|
obj = efl_constructor(efl_super(obj, MY_CLASS));
|
|
|
|
efl_event_callback_array_add(obj, _event_callback_watch(), pd);
|
|
|
|
pd->fd.in = -1;
|
|
|
|
pd->fd.out = -1;
|
|
|
|
pd->fd.can_write = EINA_TRUE;
|
|
|
|
pd->ctrl.in = -1;
|
|
|
|
pd->ctrl.out = -1;
|
|
|
|
return obj;
|
|
|
|
}
|
|
|
|
|
2019-08-26 05:46:32 -07:00
|
|
|
|
|
|
|
static void
|
|
|
|
_child_thread_del_cb(void *data, const Efl_Event *event)
|
|
|
|
{
|
|
|
|
Eo *loop = data;
|
|
|
|
Efl_Loop_Data *loop_data = efl_data_scope_get(loop, EFL_LOOP_CLASS);
|
|
|
|
|
|
|
|
if (!loop_data) return;
|
|
|
|
_efl_thread_child_remove(loop, loop_data, event->object);
|
|
|
|
if (!loop_data->quit_on_last_thread_child_del) return;
|
|
|
|
if (loop_data->thread_children) return;
|
|
|
|
// no more children waiting exits - quit the loop
|
|
|
|
_ecore_main_loop_quit(loop, loop_data);
|
|
|
|
}
|
|
|
|
|
|
|
|
EFL_CALLBACKS_ARRAY_DEFINE(thread_child_del,
|
|
|
|
{ EFL_EVENT_DEL, _child_thread_del_cb });
|
|
|
|
|
|
|
|
void
|
|
|
|
_efl_thread_child_remove(Eo *loop, Efl_Loop_Data *pd, Eo *child)
|
|
|
|
{
|
|
|
|
pd->thread_children = eina_list_remove(pd->thread_children, child);
|
|
|
|
efl_event_callback_array_del(child, thread_child_del(), loop);
|
|
|
|
}
|
|
|
|
|
|
|
|
EOLIAN static Efl_Object *
|
|
|
|
_efl_thread_efl_object_finalize(Eo *obj, Efl_Thread_Data *pd EINA_UNUSED)
|
|
|
|
{
|
|
|
|
Eo *loop = efl_provider_find(obj, EFL_LOOP_CLASS);
|
|
|
|
if (loop != obj)
|
|
|
|
{
|
|
|
|
Efl_Loop_Data *loop_data = efl_data_scope_get(loop, EFL_LOOP_CLASS);
|
|
|
|
if (loop_data)
|
|
|
|
{
|
|
|
|
loop_data->thread_children =
|
|
|
|
eina_list_prepend(loop_data->thread_children, obj);
|
|
|
|
efl_event_callback_array_add(obj, thread_child_del(), loop);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return obj;
|
|
|
|
}
|
|
|
|
|
2018-02-27 04:19:17 -08:00
|
|
|
EOLIAN static void
|
|
|
|
_efl_thread_efl_object_destructor(Eo *obj, Efl_Thread_Data *pd)
|
|
|
|
{
|
2019-09-10 15:01:19 -07:00
|
|
|
if (pd->exit_called)
|
2018-03-26 04:53:06 -07:00
|
|
|
ERR("Thread being destroyed while real worker has not exited yet.");
|
2018-02-27 04:19:17 -08:00
|
|
|
if (pd->thdat)
|
|
|
|
{
|
|
|
|
eina_thread_join(pd->thread);
|
2019-02-14 17:19:03 -08:00
|
|
|
// efl_del(pd->fd.in_handler);
|
|
|
|
// efl_del(pd->fd.out_handler);
|
|
|
|
// efl_del(pd->ctrl.in_handler);
|
|
|
|
// efl_del(pd->ctrl.out_handler);
|
2018-02-27 04:19:17 -08:00
|
|
|
close(pd->fd.in);
|
|
|
|
close(pd->fd.out);
|
|
|
|
close(pd->ctrl.in);
|
|
|
|
close(pd->ctrl.out);
|
|
|
|
pd->fd.in_handler = NULL;
|
|
|
|
pd->fd.out_handler = NULL;
|
|
|
|
pd->ctrl.in_handler = NULL;
|
|
|
|
pd->ctrl.out_handler = NULL;
|
|
|
|
pd->fd.in = -1;
|
|
|
|
pd->fd.out = -1;
|
|
|
|
pd->ctrl.in = -1;
|
|
|
|
pd->ctrl.out = -1;
|
|
|
|
free(pd->thdat);
|
|
|
|
}
|
|
|
|
free(pd->event_cb);
|
|
|
|
pd->event_cb = NULL;
|
|
|
|
efl_destructor(efl_super(obj, MY_CLASS));
|
|
|
|
}
|
|
|
|
|
|
|
|
EOLIAN static void
|
|
|
|
_efl_thread_efl_object_parent_set(Eo *obj, Efl_Thread_Data *pd, Efl_Object *parent)
|
|
|
|
{
|
|
|
|
efl_parent_set(efl_super(obj, MY_CLASS), parent);
|
|
|
|
pd->loop = efl_provider_find(parent, EFL_LOOP_CLASS);
|
|
|
|
}
|
|
|
|
|
2019-07-20 03:52:52 -07:00
|
|
|
static void
|
|
|
|
_task_run_pipe_fail_clear(Thread_Data *thdat, Efl_Thread_Data *pd)
|
|
|
|
{
|
|
|
|
efl_del(pd->fd.in_handler);
|
|
|
|
efl_del(pd->fd.out_handler);
|
|
|
|
close(thdat->fd.in);
|
|
|
|
close(thdat->fd.out);
|
|
|
|
close(pd->fd.in);
|
|
|
|
close(pd->fd.out);
|
|
|
|
pd->fd.in_handler = NULL;
|
|
|
|
pd->fd.out_handler = NULL;
|
|
|
|
pd->fd.in = -1;
|
|
|
|
pd->fd.out = -1;
|
|
|
|
free(thdat);
|
|
|
|
}
|
|
|
|
|
2019-09-10 15:01:19 -07:00
|
|
|
EOLIAN static Eina_Bool
|
2018-02-27 04:19:17 -08:00
|
|
|
_efl_thread_efl_task_run(Eo *obj, Efl_Thread_Data *pd)
|
|
|
|
{
|
|
|
|
Eina_Thread_Priority pri;
|
|
|
|
Thread_Data *thdat;
|
|
|
|
const char *name;
|
|
|
|
int pipe_to_thread[2];
|
|
|
|
int pipe_from_thread[2];
|
Revert "Revert command line array object because it's broken by design"
This reverts commit a57c7f751023fe1d1edeabbf8683574ac7497e5e.
I pretty much hate to just revert your revert, but you failed to read my
replies, and failed to understand what i was talking about.
And YES we talked at fosdem about the platform issue, and do you
remember my answer, that back in time this might be the case, today is
different freebsd suppoerts setenv, and for windows we have a setenv
implementation in evil. And yes, vtorri also created a issue how bad and
evil this commit is, however, i still fail to see the issue since setenv
unsetenv and clearenv usages are taken as needed. (T7693)
The ownership question is answered in
https://phab.enlightenment.org/D7516#137367.
Can we please get into a state of technical discussions, and not *oh
shit, i am going to revert this* this has been in review for a long
time, a lots of people have tested it, we discussed things on it, and
there was 3 weeks of no reply from you.
The issues that exist will be dealed with. Feel free to create tasks if
you want :)
2019-02-12 12:34:30 -08:00
|
|
|
unsigned int num;
|
2018-02-27 04:19:17 -08:00
|
|
|
Efl_Callback_Array_Item_Full *it;
|
2018-03-06 01:31:48 -08:00
|
|
|
Efl_Task_Data *td = efl_data_scope_get(obj, EFL_TASK_CLASS);
|
2018-02-27 04:19:17 -08:00
|
|
|
|
2019-09-10 15:01:19 -07:00
|
|
|
if (pd->run) return EINA_FALSE;
|
|
|
|
if (!td) return EINA_FALSE;
|
2018-02-27 04:19:17 -08:00
|
|
|
thdat = calloc(1, sizeof(Thread_Data));
|
2019-09-10 15:01:19 -07:00
|
|
|
if (!thdat) return EINA_FALSE;
|
2018-02-27 04:19:17 -08:00
|
|
|
thdat->fd.in = -1;
|
|
|
|
thdat->fd.out = -1;
|
|
|
|
thdat->ctrl.in = -1;
|
|
|
|
thdat->ctrl.out = -1;
|
|
|
|
|
2018-03-06 03:49:51 -08:00
|
|
|
thdat->indata = efl_threadio_indata_get(obj);
|
|
|
|
thdat->outdata = efl_threadio_outdata_get(obj);
|
|
|
|
|
2018-03-06 01:31:48 -08:00
|
|
|
// input/output pipes
|
|
|
|
if (td->flags & EFL_TASK_FLAGS_USE_STDIN)
|
2018-02-27 04:19:17 -08:00
|
|
|
{
|
2020-07-09 13:34:54 -07:00
|
|
|
if (eina_pipe_new(pipe_from_thread) != 0)
|
2018-03-06 01:31:48 -08:00
|
|
|
{
|
|
|
|
ERR("Can't create to_thread pipe");
|
|
|
|
free(thdat);
|
2019-09-10 15:01:19 -07:00
|
|
|
return EINA_FALSE;
|
2018-03-06 01:31:48 -08:00
|
|
|
}
|
2018-02-27 04:19:17 -08:00
|
|
|
}
|
2018-03-06 01:31:48 -08:00
|
|
|
if (td->flags & EFL_TASK_FLAGS_USE_STDOUT)
|
2018-02-27 04:19:17 -08:00
|
|
|
{
|
2020-07-09 13:34:54 -07:00
|
|
|
if (eina_pipe_new(pipe_to_thread) != 0)
|
2018-03-06 01:31:48 -08:00
|
|
|
{
|
|
|
|
ERR("Can't create from_thread pipe");
|
2019-08-10 15:09:06 -07:00
|
|
|
if (td->flags & EFL_TASK_FLAGS_USE_STDIN)
|
|
|
|
{
|
2019-08-10 15:17:39 -07:00
|
|
|
close(pipe_from_thread[0]);
|
|
|
|
close(pipe_from_thread[1]);
|
2019-08-10 15:09:06 -07:00
|
|
|
}
|
2018-03-06 01:31:48 -08:00
|
|
|
free(thdat);
|
2019-09-10 15:01:19 -07:00
|
|
|
return EINA_FALSE;
|
2018-03-06 01:31:48 -08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
if (td->flags & EFL_TASK_FLAGS_USE_STDIN)
|
|
|
|
{
|
|
|
|
thdat->fd.in = pipe_from_thread[1]; // write - input to parent
|
|
|
|
pd->fd.out = pipe_from_thread[0]; // read - output from child
|
|
|
|
eina_file_close_on_exec(thdat->fd.in, EINA_TRUE);
|
|
|
|
eina_file_close_on_exec(pd->fd.out, EINA_TRUE);
|
2019-01-29 02:30:45 -08:00
|
|
|
if (fcntl(thdat->fd.in, F_SETFL, O_NONBLOCK) < 0)
|
|
|
|
ERR("can't set pipe to NONBLOCK");
|
|
|
|
if (fcntl(pd->fd.out, F_SETFL, O_NONBLOCK) < 0)
|
|
|
|
ERR("can't set pipe to NONBLOCK");
|
2018-03-06 01:31:48 -08:00
|
|
|
pd->fd.out_handler =
|
|
|
|
efl_add(EFL_LOOP_HANDLER_CLASS, obj,
|
|
|
|
efl_loop_handler_fd_set(efl_added, pd->fd.out),
|
|
|
|
efl_event_callback_add
|
|
|
|
(efl_added, EFL_LOOP_HANDLER_EVENT_READ, _cb_thread_parent_out, obj));
|
|
|
|
if (pd->read_listeners > 0)
|
|
|
|
efl_loop_handler_active_set(pd->fd.out_handler, EFL_LOOP_HANDLER_FLAGS_READ);
|
|
|
|
}
|
|
|
|
if (td->flags & EFL_TASK_FLAGS_USE_STDOUT)
|
|
|
|
{
|
|
|
|
pd->fd.in = pipe_to_thread [1]; // write - input to child
|
|
|
|
thdat->fd.out = pipe_to_thread [0]; // read - output from parent
|
|
|
|
eina_file_close_on_exec(pd->fd.in, EINA_TRUE);
|
|
|
|
eina_file_close_on_exec(thdat->fd.out, EINA_TRUE);
|
2019-01-29 02:30:45 -08:00
|
|
|
if (fcntl(thdat->fd.out, F_SETFL, O_NONBLOCK) < 0)
|
|
|
|
ERR("can't set pipe to NONBLOCK");
|
|
|
|
if (fcntl(pd->fd.in, F_SETFL, O_NONBLOCK) < 0)
|
|
|
|
ERR("can't set pipe to NONBLOCK");
|
2018-03-06 01:31:48 -08:00
|
|
|
pd->fd.in_handler =
|
|
|
|
efl_add(EFL_LOOP_HANDLER_CLASS, obj,
|
|
|
|
efl_loop_handler_fd_set(efl_added, pd->fd.in),
|
|
|
|
efl_event_callback_add
|
|
|
|
(efl_added, EFL_LOOP_HANDLER_EVENT_WRITE, _cb_thread_parent_in, obj));
|
2018-02-27 04:19:17 -08:00
|
|
|
}
|
|
|
|
|
2018-03-06 01:31:48 -08:00
|
|
|
// control pipes
|
2020-07-09 13:34:54 -07:00
|
|
|
if (eina_pipe_new(pipe_to_thread) != 0)
|
2018-02-27 04:19:17 -08:00
|
|
|
{
|
|
|
|
ERR("Can't create to_thread control pipe");
|
2019-07-20 03:52:52 -07:00
|
|
|
_task_run_pipe_fail_clear(thdat, pd);
|
2019-09-10 15:01:19 -07:00
|
|
|
return EINA_FALSE;
|
2018-02-27 04:19:17 -08:00
|
|
|
}
|
2020-07-09 13:34:54 -07:00
|
|
|
if (eina_pipe_new(pipe_from_thread) != 0)
|
2018-02-27 04:19:17 -08:00
|
|
|
{
|
|
|
|
ERR("Can't create from_thread control pipe");
|
2019-07-20 03:52:52 -07:00
|
|
|
_task_run_pipe_fail_clear(thdat, pd);
|
2018-02-27 04:19:17 -08:00
|
|
|
close(pipe_to_thread[0]);
|
|
|
|
close(pipe_to_thread[1]);
|
2019-09-10 15:01:19 -07:00
|
|
|
return EINA_FALSE;
|
2018-02-27 04:19:17 -08:00
|
|
|
}
|
|
|
|
thdat->ctrl.in = pipe_from_thread[1]; // write - input to parent
|
|
|
|
thdat->ctrl.out = pipe_to_thread [0]; // read - output from parent
|
|
|
|
pd->ctrl.in = pipe_to_thread [1]; // write - input to child
|
|
|
|
pd->ctrl.out = pipe_from_thread[0]; // read - output from child
|
2019-01-29 02:30:45 -08:00
|
|
|
if (fcntl(thdat->ctrl.in, F_SETFL, O_NONBLOCK) < 0)
|
|
|
|
ERR("can't set pipe to NONBLOCK");
|
|
|
|
if (fcntl(thdat->ctrl.out, F_SETFL, O_NONBLOCK) < 0)
|
|
|
|
ERR("can't set pipe to NONBLOCK");
|
|
|
|
if (fcntl(pd->ctrl.in, F_SETFL, O_NONBLOCK) < 0)
|
|
|
|
ERR("can't set pipe to NONBLOCK");
|
|
|
|
if (fcntl(pd->ctrl.out, F_SETFL, O_NONBLOCK) < 0)
|
|
|
|
ERR("can't set pipe to NONBLOCK");
|
2018-02-27 04:19:17 -08:00
|
|
|
eina_file_close_on_exec(pd->ctrl.in, EINA_TRUE);
|
|
|
|
eina_file_close_on_exec(pd->ctrl.out, EINA_TRUE);
|
|
|
|
eina_file_close_on_exec(thdat->ctrl.in, EINA_TRUE);
|
|
|
|
eina_file_close_on_exec(thdat->ctrl.out, EINA_TRUE);
|
|
|
|
pd->ctrl.in_handler =
|
|
|
|
efl_add(EFL_LOOP_HANDLER_CLASS, obj,
|
|
|
|
efl_loop_handler_fd_set(efl_added, pd->ctrl.in));
|
|
|
|
pd->ctrl.out_handler =
|
|
|
|
efl_add(EFL_LOOP_HANDLER_CLASS, obj,
|
|
|
|
efl_loop_handler_fd_set(efl_added, pd->ctrl.out),
|
|
|
|
efl_event_callback_add
|
|
|
|
(efl_added, EFL_LOOP_HANDLER_EVENT_READ, _cb_thread_parent_ctrl_out, obj),
|
|
|
|
efl_loop_handler_active_set
|
|
|
|
(efl_added, EFL_LOOP_HANDLER_FLAGS_READ));
|
|
|
|
|
|
|
|
switch (efl_task_priority_get(obj))
|
|
|
|
{
|
|
|
|
case EFL_TASK_PRIORITY_BACKGROUND:
|
|
|
|
pri = EINA_THREAD_IDLE;
|
|
|
|
break;
|
|
|
|
case EFL_TASK_PRIORITY_HIGH:
|
|
|
|
case EFL_TASK_PRIORITY_ULTRA:
|
|
|
|
pri = EINA_THREAD_URGENT;
|
|
|
|
break;
|
|
|
|
case EFL_TASK_PRIORITY_LOW:
|
|
|
|
pri = EINA_THREAD_BACKGROUND;
|
|
|
|
break;
|
|
|
|
case EFL_TASK_PRIORITY_NORMAL:
|
|
|
|
default:
|
|
|
|
pri = EINA_THREAD_NORMAL;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
name = efl_name_get(obj);
|
|
|
|
if (name) thdat->name = eina_stringshare_add(name);
|
|
|
|
|
Revert "Revert command line array object because it's broken by design"
This reverts commit a57c7f751023fe1d1edeabbf8683574ac7497e5e.
I pretty much hate to just revert your revert, but you failed to read my
replies, and failed to understand what i was talking about.
And YES we talked at fosdem about the platform issue, and do you
remember my answer, that back in time this might be the case, today is
different freebsd suppoerts setenv, and for windows we have a setenv
implementation in evil. And yes, vtorri also created a issue how bad and
evil this commit is, however, i still fail to see the issue since setenv
unsetenv and clearenv usages are taken as needed. (T7693)
The ownership question is answered in
https://phab.enlightenment.org/D7516#137367.
Can we please get into a state of technical discussions, and not *oh
shit, i am going to revert this* this has been in review for a long
time, a lots of people have tested it, we discussed things on it, and
there was 3 weeks of no reply from you.
The issues that exist will be dealed with. Feel free to create tasks if
you want :)
2019-02-12 12:34:30 -08:00
|
|
|
{
|
|
|
|
Eina_Accessor *acc;
|
|
|
|
int i = 0;
|
|
|
|
const char *argv;
|
|
|
|
|
|
|
|
acc = efl_core_command_line_command_access(obj);
|
|
|
|
if (acc)
|
|
|
|
{
|
2019-02-14 17:16:49 -08:00
|
|
|
thdat->argv = eina_array_new(1);
|
Revert "Revert command line array object because it's broken by design"
This reverts commit a57c7f751023fe1d1edeabbf8683574ac7497e5e.
I pretty much hate to just revert your revert, but you failed to read my
replies, and failed to understand what i was talking about.
And YES we talked at fosdem about the platform issue, and do you
remember my answer, that back in time this might be the case, today is
different freebsd suppoerts setenv, and for windows we have a setenv
implementation in evil. And yes, vtorri also created a issue how bad and
evil this commit is, however, i still fail to see the issue since setenv
unsetenv and clearenv usages are taken as needed. (T7693)
The ownership question is answered in
https://phab.enlightenment.org/D7516#137367.
Can we please get into a state of technical discussions, and not *oh
shit, i am going to revert this* this has been in review for a long
time, a lots of people have tested it, we discussed things on it, and
there was 3 weeks of no reply from you.
The issues that exist will be dealed with. Feel free to create tasks if
you want :)
2019-02-12 12:34:30 -08:00
|
|
|
EINA_ACCESSOR_FOREACH(acc, i, argv)
|
|
|
|
{
|
|
|
|
eina_array_push(thdat->argv, eina_stringshare_add(argv));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2018-02-27 04:19:17 -08:00
|
|
|
if (pd->event_cb)
|
|
|
|
{
|
|
|
|
num = 0;
|
|
|
|
for (it = pd->event_cb; it->func; it++) num++;
|
|
|
|
thdat->event_cb = malloc((num + 1) * sizeof(Efl_Callback_Array_Item_Full));
|
|
|
|
if (thdat->event_cb)
|
|
|
|
memcpy(thdat->event_cb, pd->event_cb,
|
|
|
|
(num + 1) * sizeof(Efl_Callback_Array_Item_Full));
|
|
|
|
// XXX: if malloc fails?
|
|
|
|
}
|
|
|
|
|
|
|
|
// env data - ignore as other end will share same env
|
|
|
|
|
|
|
|
if (!eina_thread_create(&(pd->thread), pri, -1, _efl_thread_main, thdat))
|
|
|
|
{
|
Revert "Revert command line array object because it's broken by design"
This reverts commit a57c7f751023fe1d1edeabbf8683574ac7497e5e.
I pretty much hate to just revert your revert, but you failed to read my
replies, and failed to understand what i was talking about.
And YES we talked at fosdem about the platform issue, and do you
remember my answer, that back in time this might be the case, today is
different freebsd suppoerts setenv, and for windows we have a setenv
implementation in evil. And yes, vtorri also created a issue how bad and
evil this commit is, however, i still fail to see the issue since setenv
unsetenv and clearenv usages are taken as needed. (T7693)
The ownership question is answered in
https://phab.enlightenment.org/D7516#137367.
Can we please get into a state of technical discussions, and not *oh
shit, i am going to revert this* this has been in review for a long
time, a lots of people have tested it, we discussed things on it, and
there was 3 weeks of no reply from you.
The issues that exist will be dealed with. Feel free to create tasks if
you want :)
2019-02-12 12:34:30 -08:00
|
|
|
while (eina_array_count(thdat->argv)) eina_stringshare_del(eina_array_pop(thdat->argv));
|
|
|
|
eina_array_free(thdat->argv);
|
2018-02-27 04:19:17 -08:00
|
|
|
efl_del(pd->fd.in_handler);
|
|
|
|
efl_del(pd->fd.out_handler);
|
|
|
|
efl_del(pd->ctrl.in_handler);
|
|
|
|
efl_del(pd->ctrl.out_handler);
|
|
|
|
close(pd->fd.in);
|
|
|
|
close(pd->fd.out);
|
|
|
|
close(pd->ctrl.in);
|
|
|
|
close(pd->ctrl.out);
|
2020-09-19 16:06:30 -07:00
|
|
|
if (thdat->fd.in >= 0) close(thdat->fd.in);
|
|
|
|
if (thdat->fd.out >= 0) close(thdat->fd.out);
|
2018-02-27 04:19:17 -08:00
|
|
|
close(thdat->ctrl.in);
|
|
|
|
close(thdat->ctrl.out);
|
|
|
|
free(thdat);
|
|
|
|
pd->fd.in_handler = NULL;
|
|
|
|
pd->fd.out_handler = NULL;
|
|
|
|
pd->ctrl.in_handler = NULL;
|
|
|
|
pd->ctrl.out_handler = NULL;
|
|
|
|
pd->fd.in = -1;
|
|
|
|
pd->fd.out = -1;
|
|
|
|
pd->ctrl.in = -1;
|
|
|
|
pd->ctrl.out = -1;
|
2019-09-10 15:01:19 -07:00
|
|
|
return EINA_FALSE;
|
2018-02-27 04:19:17 -08:00
|
|
|
}
|
|
|
|
pd->thdat = thdat;
|
2018-03-10 03:02:09 -08:00
|
|
|
pd->run = EINA_TRUE;
|
2019-09-10 15:01:19 -07:00
|
|
|
return EINA_TRUE;
|
2018-02-27 04:19:17 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
EOLIAN static void
|
|
|
|
_efl_thread_efl_task_end(Eo *obj EINA_UNUSED, Efl_Thread_Data *pd)
|
|
|
|
{
|
|
|
|
if (pd->end_sent) return;
|
2019-08-26 05:46:32 -07:00
|
|
|
if ((pd->thdat) && (!pd->exit_called))
|
2018-02-27 04:19:17 -08:00
|
|
|
{
|
|
|
|
Control_Data cmd;
|
|
|
|
|
|
|
|
pd->end_sent = EINA_TRUE;
|
2018-03-06 03:49:51 -08:00
|
|
|
memset(&cmd, 0, sizeof(cmd));
|
|
|
|
cmd.d.command = CMD_EXIT;
|
2019-06-20 03:24:57 -07:00
|
|
|
_efl_thread_pipe_write(pd->ctrl.in, &cmd, sizeof(Control_Data));
|
2018-02-27 04:19:17 -08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
EOLIAN static Eina_Error
|
|
|
|
_efl_thread_efl_io_closer_close(Eo *obj, Efl_Thread_Data *pd)
|
|
|
|
{
|
|
|
|
if (!pd->thdat) return 0;
|
|
|
|
EINA_SAFETY_ON_TRUE_RETURN_VAL(efl_io_closer_closed_get(obj), EBADF);
|
|
|
|
efl_io_writer_can_write_set(obj, EINA_FALSE);
|
|
|
|
efl_io_reader_can_read_set(obj, EINA_FALSE);
|
|
|
|
efl_io_reader_eos_set(obj, EINA_TRUE);
|
|
|
|
if (pd->fd.in >= 0) close(pd->fd.in);
|
|
|
|
if (pd->fd.out >= 0) close(pd->fd.out);
|
|
|
|
if (pd->fd.in_handler) efl_del(pd->fd.in_handler);
|
|
|
|
if (pd->fd.out_handler) efl_del(pd->fd.out_handler);
|
|
|
|
pd->fd.in = -1;
|
|
|
|
pd->fd.out = -1;
|
|
|
|
pd->fd.in_handler = NULL;
|
|
|
|
pd->fd.out_handler = NULL;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
EOLIAN static Eina_Bool
|
2018-04-17 11:09:44 -07:00
|
|
|
_efl_thread_efl_io_closer_closed_get(const Eo *obj EINA_UNUSED, Efl_Thread_Data *pd)
|
2018-02-27 04:19:17 -08:00
|
|
|
{
|
|
|
|
if ((pd->fd.in == -1) && (pd->fd.out == -1)) return EINA_TRUE;
|
|
|
|
return EINA_FALSE;
|
|
|
|
}
|
|
|
|
|
2019-07-20 03:48:30 -07:00
|
|
|
static void
|
|
|
|
_io_reader_read_fd_out_clear(Efl_Thread_Data *pd)
|
|
|
|
{
|
|
|
|
close(pd->fd.out);
|
|
|
|
pd->fd.out = -1;
|
|
|
|
efl_del(pd->fd.out_handler);
|
|
|
|
pd->fd.out_handler = NULL;
|
|
|
|
}
|
|
|
|
|
2018-02-27 04:19:17 -08:00
|
|
|
EOLIAN static Eina_Error
|
|
|
|
_efl_thread_efl_io_reader_read(Eo *obj, Efl_Thread_Data *pd, Eina_Rw_Slice *rw_slice)
|
|
|
|
{
|
|
|
|
ssize_t r;
|
|
|
|
|
|
|
|
errno = 0;
|
|
|
|
if (pd->fd.out == -1) goto err;
|
|
|
|
|
|
|
|
do
|
|
|
|
{
|
|
|
|
errno = 0;
|
|
|
|
r = read(pd->fd.out, rw_slice->mem, rw_slice->len);
|
|
|
|
if (r == -1)
|
|
|
|
{
|
|
|
|
if (errno == EINTR) continue;
|
|
|
|
goto err;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
while (r == -1);
|
|
|
|
|
|
|
|
rw_slice->len = r;
|
|
|
|
if (r == 0)
|
|
|
|
{
|
|
|
|
efl_io_reader_can_read_set(obj, EINA_FALSE);
|
|
|
|
efl_io_reader_eos_set(obj, EINA_TRUE);
|
2019-07-20 03:48:30 -07:00
|
|
|
_io_reader_read_fd_out_clear(pd);
|
2018-02-27 04:19:17 -08:00
|
|
|
_thread_exit_eval(obj, pd);
|
|
|
|
return EPIPE;
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
err:
|
|
|
|
if ((pd->fd.out != -1) && (errno != EAGAIN))
|
2019-07-20 03:48:30 -07:00
|
|
|
_io_reader_read_fd_out_clear(pd);
|
2018-02-27 04:19:17 -08:00
|
|
|
rw_slice->len = 0;
|
|
|
|
rw_slice->mem = NULL;
|
|
|
|
efl_io_reader_can_read_set(obj, EINA_FALSE);
|
|
|
|
_thread_exit_eval(obj, pd);
|
|
|
|
return EINVAL;
|
|
|
|
}
|
|
|
|
|
|
|
|
EOLIAN static void
|
|
|
|
_efl_thread_efl_io_reader_can_read_set(Eo *obj, Efl_Thread_Data *pd, Eina_Bool can_read)
|
|
|
|
{
|
|
|
|
Eina_Bool old = efl_io_reader_can_read_get(obj);
|
|
|
|
if (old == can_read) return;
|
|
|
|
pd->fd.can_read = can_read;
|
|
|
|
if (!pd->fd.out_handler) return;
|
|
|
|
if (can_read)
|
|
|
|
efl_loop_handler_active_set(pd->fd.out_handler, 0);
|
|
|
|
else
|
|
|
|
efl_loop_handler_active_set(pd->fd.out_handler,
|
|
|
|
EFL_LOOP_HANDLER_FLAGS_READ);
|
2019-03-19 13:32:02 -07:00
|
|
|
efl_event_callback_call(obj, EFL_IO_READER_EVENT_CAN_READ_CHANGED, &can_read);
|
2018-02-27 04:19:17 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
EOLIAN static Eina_Bool
|
2018-04-17 11:09:44 -07:00
|
|
|
_efl_thread_efl_io_reader_can_read_get(const Eo *obj EINA_UNUSED, Efl_Thread_Data *pd)
|
2018-02-27 04:19:17 -08:00
|
|
|
{
|
|
|
|
return pd->fd.can_read;
|
|
|
|
}
|
|
|
|
|
|
|
|
EOLIAN static void
|
|
|
|
_efl_thread_efl_io_reader_eos_set(Eo *obj, Efl_Thread_Data *pd, Eina_Bool is_eos)
|
|
|
|
{
|
|
|
|
Eina_Bool old = efl_io_reader_eos_get(obj);
|
|
|
|
if (old == is_eos) return;
|
|
|
|
|
|
|
|
pd->fd.eos_read = is_eos;
|
|
|
|
if (!is_eos) return;
|
|
|
|
if (pd->fd.out_handler)
|
|
|
|
efl_loop_handler_active_set(pd->fd.out_handler, 0);
|
|
|
|
efl_event_callback_call(obj, EFL_IO_READER_EVENT_EOS, NULL);
|
|
|
|
}
|
|
|
|
|
|
|
|
EOLIAN static Eina_Bool
|
2018-04-17 11:09:44 -07:00
|
|
|
_efl_thread_efl_io_reader_eos_get(const Eo *obj EINA_UNUSED, Efl_Thread_Data *pd)
|
2018-02-27 04:19:17 -08:00
|
|
|
{
|
|
|
|
return pd->fd.eos_read;
|
|
|
|
}
|
|
|
|
|
2019-07-20 03:46:07 -07:00
|
|
|
static void
|
|
|
|
_io_writer_write_fd_in_clear(Efl_Thread_Data *pd)
|
|
|
|
{
|
|
|
|
close(pd->fd.in);
|
|
|
|
pd->fd.in = -1;
|
|
|
|
efl_del(pd->fd.in_handler);
|
|
|
|
pd->fd.in_handler = NULL;
|
|
|
|
}
|
|
|
|
|
2018-02-27 04:19:17 -08:00
|
|
|
EOLIAN static Eina_Error
|
|
|
|
_efl_thread_efl_io_writer_write(Eo *obj, Efl_Thread_Data *pd, Eina_Slice *slice, Eina_Slice *remaining)
|
|
|
|
{
|
|
|
|
ssize_t r;
|
|
|
|
|
|
|
|
errno = 0;
|
|
|
|
if (pd->fd.in == -1) goto err;
|
2019-10-18 10:30:03 -07:00
|
|
|
if (!slice) return EINVAL;
|
2018-02-27 04:19:17 -08:00
|
|
|
|
|
|
|
do
|
|
|
|
{
|
|
|
|
errno = 0;
|
|
|
|
r = write(pd->fd.in, slice->mem, slice->len);
|
|
|
|
if (r == -1)
|
|
|
|
{
|
|
|
|
if (errno == EINTR) continue;
|
|
|
|
goto err;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
while (r == -1);
|
|
|
|
|
|
|
|
if (remaining)
|
|
|
|
{
|
|
|
|
remaining->len = slice->len - r;
|
|
|
|
remaining->bytes = slice->bytes + r;
|
|
|
|
}
|
|
|
|
slice->len = r;
|
|
|
|
|
2019-10-18 10:30:03 -07:00
|
|
|
if (slice->len > 0)
|
2018-02-27 04:19:17 -08:00
|
|
|
efl_io_writer_can_write_set(obj, EINA_FALSE);
|
|
|
|
if (r == 0)
|
|
|
|
{
|
2019-07-20 03:46:07 -07:00
|
|
|
_io_writer_write_fd_in_clear(pd);
|
2018-02-27 04:19:17 -08:00
|
|
|
_thread_exit_eval(obj, pd);
|
|
|
|
return EPIPE;
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
err:
|
|
|
|
if ((pd->fd.in != -1) && (errno != EAGAIN))
|
2019-07-20 03:46:07 -07:00
|
|
|
_io_writer_write_fd_in_clear(pd);
|
2018-02-27 04:19:17 -08:00
|
|
|
if (remaining) *remaining = *slice;
|
|
|
|
slice->len = 0;
|
|
|
|
slice->mem = NULL;
|
|
|
|
efl_io_writer_can_write_set(obj, EINA_FALSE);
|
|
|
|
_thread_exit_eval(obj, pd);
|
|
|
|
return EINVAL;
|
|
|
|
}
|
|
|
|
|
|
|
|
EOLIAN static void
|
|
|
|
_efl_thread_efl_io_writer_can_write_set(Eo *obj, Efl_Thread_Data *pd, Eina_Bool can_write)
|
|
|
|
{
|
|
|
|
Eina_Bool old = efl_io_writer_can_write_get(obj);
|
|
|
|
if (old == can_write) return;
|
|
|
|
pd->fd.can_write = can_write;
|
|
|
|
if (can_write)
|
|
|
|
efl_loop_handler_active_set(pd->fd.in_handler, 0);
|
|
|
|
else
|
|
|
|
efl_loop_handler_active_set(pd->fd.in_handler,
|
|
|
|
EFL_LOOP_HANDLER_FLAGS_WRITE);
|
2019-03-19 13:32:02 -07:00
|
|
|
efl_event_callback_call(obj, EFL_IO_WRITER_EVENT_CAN_WRITE_CHANGED, &can_write);
|
2018-02-27 04:19:17 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
EOLIAN static Eina_Bool
|
2018-04-17 11:09:44 -07:00
|
|
|
_efl_thread_efl_io_writer_can_write_get(const Eo *obj EINA_UNUSED, Efl_Thread_Data *pd)
|
2018-02-27 04:19:17 -08:00
|
|
|
{
|
|
|
|
return pd->fd.can_write;
|
|
|
|
}
|
|
|
|
|
2019-07-20 03:44:05 -07:00
|
|
|
static void
|
2019-07-30 06:36:32 -07:00
|
|
|
_threadio_call(int fd, void *func_data, EflThreadIOCall func, Eina_Free_Cb func_free_cb)
|
2018-03-06 03:49:51 -08:00
|
|
|
{
|
|
|
|
Control_Data cmd;
|
|
|
|
|
|
|
|
memset(&cmd, 0, sizeof(cmd));
|
|
|
|
cmd.d.command = CMD_CALL;
|
|
|
|
cmd.d.ptr[0] = func;
|
|
|
|
cmd.d.ptr[1] = func_data;
|
|
|
|
cmd.d.ptr[2] = func_free_cb;
|
2019-07-20 03:44:05 -07:00
|
|
|
_efl_thread_pipe_write(fd, &cmd, sizeof(Control_Data));
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
_appthread_threadio_call(Eo *obj EINA_UNUSED, Efl_Appthread_Data *pd,
|
2019-07-30 06:36:32 -07:00
|
|
|
void *func_data, EflThreadIOCall func, Eina_Free_Cb func_free_cb)
|
2019-07-20 03:44:05 -07:00
|
|
|
{
|
|
|
|
Thread_Data *thdat = pd->thdat;
|
|
|
|
_threadio_call(thdat->ctrl.in, func_data, func, func_free_cb);
|
2018-03-06 03:49:51 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
EOLIAN static void
|
|
|
|
_efl_thread_efl_threadio_call(Eo *obj EINA_UNUSED, Efl_Thread_Data *pd,
|
2019-07-30 06:36:32 -07:00
|
|
|
void *func_data, EflThreadIOCall func, Eina_Free_Cb func_free_cb)
|
2019-07-20 03:44:05 -07:00
|
|
|
{
|
|
|
|
_threadio_call(pd->ctrl.in, func_data, func, func_free_cb);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void *
|
2019-07-30 06:36:32 -07:00
|
|
|
_threadio_call_sync(int fd, void *func_data, EflThreadIOCallSync func, Eina_Free_Cb func_free_cb)
|
2018-03-06 03:49:51 -08:00
|
|
|
{
|
|
|
|
Control_Data cmd;
|
2019-07-20 03:44:05 -07:00
|
|
|
Control_Reply rep;
|
2018-03-06 03:49:51 -08:00
|
|
|
|
|
|
|
memset(&cmd, 0, sizeof(cmd));
|
2019-07-20 03:44:05 -07:00
|
|
|
cmd.d.command = CMD_CALL_SYNC;
|
2018-03-06 03:49:51 -08:00
|
|
|
cmd.d.ptr[0] = func;
|
|
|
|
cmd.d.ptr[1] = func_data;
|
|
|
|
cmd.d.ptr[2] = func_free_cb;
|
2019-07-20 03:44:05 -07:00
|
|
|
cmd.d.ptr[3] = &rep;
|
|
|
|
rep.data = NULL;
|
|
|
|
eina_semaphore_new(&(rep.sem), 0);
|
|
|
|
_efl_thread_pipe_write(fd, &cmd, sizeof(Control_Data));
|
|
|
|
eina_semaphore_lock(&(rep.sem));
|
|
|
|
return rep.data;
|
2018-03-06 03:49:51 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
void *
|
|
|
|
_appthread_threadio_call_sync(Eo *obj EINA_UNUSED, Efl_Appthread_Data *pd,
|
2019-07-30 06:36:32 -07:00
|
|
|
void *func_data, EflThreadIOCallSync func, Eina_Free_Cb func_free_cb)
|
2018-03-06 03:49:51 -08:00
|
|
|
{
|
|
|
|
Thread_Data *thdat = pd->thdat;
|
2019-07-20 03:44:05 -07:00
|
|
|
return _threadio_call_sync(thdat->ctrl.in, func_data, func, func_free_cb);
|
2018-03-06 03:49:51 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
EOLIAN static void *
|
|
|
|
_efl_thread_efl_threadio_call_sync(Eo *obj EINA_UNUSED, Efl_Thread_Data *pd,
|
2019-07-30 06:36:32 -07:00
|
|
|
void *func_data, EflThreadIOCallSync func, Eina_Free_Cb func_free_cb)
|
2018-03-06 03:49:51 -08:00
|
|
|
{
|
2019-07-20 03:44:05 -07:00
|
|
|
return _threadio_call_sync(pd->ctrl.in, func_data, func, func_free_cb);
|
2018-03-06 03:49:51 -08:00
|
|
|
}
|
|
|
|
|
2018-02-27 04:19:17 -08:00
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
#include "efl_thread.eo.c"
|