evas/cserve2: Add threaded slave support.
authorantognolli <antognolli@7cbeb6ba-43b4-40fd-8cce-4c39aea84d33>
Thu, 31 May 2012 21:33:37 +0000 (21:33 +0000)
committerantognolli <antognolli@7cbeb6ba-43b4-40fd-8cce-4c39aea84d33>
Thu, 31 May 2012 21:33:37 +0000 (21:33 +0000)
It's not being used yet, but the font slave will be done using this
code.

git-svn-id: svn+ssh://svn.enlightenment.org/var/svn/e/trunk/evas@71598 7cbeb6ba-43b4-40fd-8cce-4c39aea84d33

src/bin/evas_cserve2.h
src/bin/evas_cserve2_slaves.c

index b6c44a0..ce0fbbc 100644 (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);
 
index b50275e..7f60b69 100644 (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)
@@ -90,6 +107,21 @@ _slave_proc_free(Slave_Proc *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__)
 {
    Slave_Proc *s;
@@ -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(sp->pid, SIGKILL);
+        _slave_proc_free(sp);
+     }
+
+   EINA_LIST_FOREACH(slave_threads, l, st)
+      pthread_cancel(st->tid);
+
+   EINA_LIST_FREE(slave_threads, st)
      {
-        kill(s->pid, SIGKILL);
-        _slave_proc_free(s);
+        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)
 {