evas/cserve2: Add threaded slave support.

It's not being used yet, but the font slave will be done using this
code.



SVN revision: 71598
This commit is contained in:
Rafael Antognolli 2012-05-31 21:33:37 +00:00
parent 616873f46d
commit 9a469b778c
2 changed files with 158 additions and 5 deletions

View File

@ -24,6 +24,7 @@
extern int _evas_cserve2_bin_log_dom;
typedef struct _Slave Slave;
typedef struct _Slave_Thread_Data Slave_Thread_Data;
typedef struct _Shm_Handle Shm_Handle;
typedef enum {
@ -117,6 +118,7 @@ typedef void (*Timeout_Cb)(void); /* void* for compat? */
typedef void (*Main_Loop_Child_Dead_Cb)(int pid, int status); /* void* for compat? */
typedef void (*Slave_Dead_Cb)(Slave *slave, void *data);
typedef void (*Slave_Read_Cb)(Slave *slave, Slave_Command cmd, void *msg, void *data);
typedef void (*Slave_Thread_Cb)(Slave_Thread_Data *sd, void *data);
typedef void (*File_Change_Cb)(const char *path, Eina_Bool deleted, void *data);
void cserve2_client_accept(int fd);
@ -148,6 +150,7 @@ void cserve2_slaves_shutdown(void);
int cserve2_slave_available_get(void);
Eina_Bool cserve2_slave_cmd_dispatch(void *data, Slave_Command cmd, const void *msg, int size);
Slave *cserve2_slave_run(const char *exe, Slave_Read_Cb read_cb, Slave_Dead_Cb dead_cb, const void *data);
Slave *cserve2_slave_thread_run(Slave_Thread_Cb thread_cb, void *thread_data, Slave_Read_Cb read_cb, Slave_Dead_Cb dead_cb, const void *data);
void cserve2_slave_send(Slave *s, Slave_Command cmd, const char *data, size_t size);
void cserve2_slave_kill(Slave *s);

View File

@ -42,9 +42,26 @@ struct _Slave_Proc
Eina_Bool killed : 1;
};
typedef struct _Slave_Thread Slave_Thread;
typedef struct _Slave_Proc Slave_Proc;
struct _Slave_Thread
{
Slave base;
pthread_t tid;
Slave_Thread_Data *tdata;
};
struct _Slave_Thread_Data {
int write_fd;
int read_fd;
Slave_Thread_Cb cb;
void *cb_data;
};
static Eina_List *slave_procs;
static Eina_List *slave_threads;
static pthread_attr_t slave_thread_attr;
static Slave_Proc *
_slave_proc_find(pid_t pid)
@ -89,6 +106,21 @@ _slave_proc_free(Slave_Proc *s)
free(s);
}
static void
_slave_thread_free(Slave_Thread *s)
{
Slave_Thread_Data *sd = s->tdata;
close(sd->write_fd);
close(sd->read_fd);
free(sd);
_slave_free((Slave *)s);
free(s);
}
static void
_slave_proc_dead_cb(int pid, int status __UNUSED__)
{
@ -220,26 +252,44 @@ Eina_Bool
cserve2_slaves_init(void)
{
cserve2_on_child_dead_set(_slave_proc_dead_cb);
if (pthread_attr_init(&slave_thread_attr))
{
ERR("Could not initialize attributes for thread.");
cserve2_on_child_dead_set(NULL);
return EINA_FALSE;
}
return EINA_TRUE;
}
void
cserve2_slaves_shutdown(void)
{
Slave_Proc *s;
Slave_Proc *sp;
Slave_Thread *st;
Eina_List *l;
cserve2_on_child_dead_set(NULL);
if (!slave_procs)
if (!slave_procs && !slave_threads)
return;
DBG("Shutting down slaves subsystem with %d slaves alive!",
eina_list_count(slave_procs));
EINA_LIST_FREE(slave_procs, s)
EINA_LIST_FREE(slave_procs, sp)
{
kill(s->pid, SIGKILL);
_slave_proc_free(s);
kill(sp->pid, SIGKILL);
_slave_proc_free(sp);
}
EINA_LIST_FOREACH(slave_threads, l, st)
pthread_cancel(st->tid);
EINA_LIST_FREE(slave_threads, st)
{
pthread_join(st->tid, NULL);
_slave_thread_free(st);
}
}
@ -376,6 +426,106 @@ cserve2_slave_run(const char *name, Slave_Read_Cb read_cb, Slave_Dead_Cb dead_cb
return _cserve2_slave_proc_run(name, read_cb, dead_cb, data);
}
static void *
_slave_thread_cb(void *data)
{
Slave_Thread_Data *sd = data;
sd->cb(sd, sd->cb_data);
return NULL;
}
Slave *
cserve2_slave_thread_run(Slave_Thread_Cb thread_cb, void *thread_data, Slave_Read_Cb read_cb, Slave_Dead_Cb dead_cb, const void *data)
{
Slave_Thread_Data *sd;
Slave_Thread *s;
Slave *sb;
pthread_t tid;
int child[2], parent[2];
int flags;
s = calloc(1, sizeof(Slave_Thread));
if (!s)
{
ERR("Could not create Slave_Thread handler.");
return NULL;
}
sb = (Slave *)s;
sd = calloc(1, sizeof(Slave_Thread_Data));
if (!sd)
{
ERR("Could not create Slave_Thread_Data.");
return NULL;
}
if (pipe(child))
{
ERR("Could not create pipes for child.");
free(s);
free(sd);
return NULL;
}
if (pipe(parent))
{
ERR("Could not create pipes for parent.");
free(s);
free(sd);
close(child[0]);
close(child[1]);
return NULL;
}
/* Setting data for slave thread */
sd->read_fd = child[0];
flags = fcntl(sd->read_fd, F_GETFL);
flags |= O_NONBLOCK;
fcntl(sd->read_fd, F_SETFL, flags);
sd->write_fd = parent[1];
flags = fcntl(sd->write_fd, F_GETFL);
flags |= O_NONBLOCK;
fcntl(sd->write_fd, F_SETFL, flags);
sd->cb = thread_cb;
sd->cb_data = thread_data;
if (pthread_create(&tid, &slave_thread_attr, _slave_thread_cb, sd))
{
ERR("Could not start slave thread.");
free(s);
free(sd);
close(child[0]);
close(child[1]);
close(parent[0]);
close(parent[1]);
return NULL;
}
s->tid = tid;
s->tdata = sd;
sb->type = SLAVE_THREAD;
sb->write_fd = child[1];
flags = fcntl(sb->write_fd, F_GETFL);
flags |= O_NONBLOCK;
fcntl(sb->write_fd, F_SETFL, flags);
sb->read_fd = parent[0];
flags = fcntl(sb->read_fd, F_GETFL);
flags |= O_NONBLOCK;
fcntl(sb->read_fd, F_SETFL, flags);
sb->read_cb = read_cb;
sb->dead_cb = dead_cb;
sb->data = data;
cserve2_fd_watch_add(sb->read_fd, FD_READ, _slave_read_cb, sb);
slave_threads = eina_list_append(slave_threads, s);
return sb;
}
static void
_slave_send_aux(Slave *s, const char *data, size_t size)
{