From a3fa30f70b766a4421175fc68b2a15daeaa0ba3c Mon Sep 17 00:00:00 2001 From: Rafael Antognolli Date: Thu, 31 May 2012 21:33:59 +0000 Subject: [PATCH] evas/cserve2: Add requests and slave workers management. SVN revision: 71601 --- legacy/evas/src/bin/evas_cserve2.h | 8 +- legacy/evas/src/bin/evas_cserve2_requests.c | 225 +++++++++++++++++++- 2 files changed, 226 insertions(+), 7 deletions(-) diff --git a/legacy/evas/src/bin/evas_cserve2.h b/legacy/evas/src/bin/evas_cserve2.h index cdfe857964..dc6c21c51d 100644 --- a/legacy/evas/src/bin/evas_cserve2.h +++ b/legacy/evas/src/bin/evas_cserve2.h @@ -113,12 +113,14 @@ typedef struct _Slave_Msg_Image_Opened Slave_Msg_Image_Opened; typedef struct _Slave_Msg_Image_Load Slave_Msg_Image_Load; typedef struct _Slave_Msg_Image_Loaded Slave_Msg_Image_Loaded; -typedef void *(*Font_Request_Msg_Create)(Client *c, void *data, int *size); -typedef void (*Font_Request_Response)(Client *c, void *data, void *resp); -typedef void (*Font_Request_Error)(Client *c, void *data, Error_Type error); +typedef void *(*Font_Request_Msg_Create)(void *data, int *size); +typedef void *(*Font_Request_Msg_Free)(void *data); +typedef void (*Font_Request_Response)(Client *c, void *data, void *resp, unsigned int rid); +typedef void (*Font_Request_Error)(Client *c, void *data, Error_Type error, unsigned int rid); struct _Font_Request_Funcs { Font_Request_Msg_Create msg_create; + Font_Request_Msg_Free msg_free; Font_Request_Response response; Font_Request_Error error; }; diff --git a/legacy/evas/src/bin/evas_cserve2_requests.c b/legacy/evas/src/bin/evas_cserve2_requests.c index ddfa3f8f40..84bd1b176e 100644 --- a/legacy/evas/src/bin/evas_cserve2_requests.c +++ b/legacy/evas/src/bin/evas_cserve2_requests.c @@ -4,15 +4,72 @@ #include "evas_cserve2.h" -struct _Font_Request { +#define MAX_SLAVES 1 + +typedef enum +{ + SLAVE_IMAGE, + SLAVE_FONT, + SLAVE_NONE +} Slave_Type; + +struct _Slave_Worker +{ + void *data; + Slave *slave; + Eina_Binbuf *ret; + int ret_size; + Eina_Bool done; + Eina_Bool delete_me; +}; + +typedef struct _Slave_Worker Slave_Worker; + +/* This struct is used to match font request types to the respective slave + * type, and the message type that will be used for that request. The order + * of the request types on it is the order in which these requests will + * be processed. + */ +static struct _Request_Match +{ + Font_Request_Type rtype; + Slave_Type stype; + Message_Type mtype; +} _request_match[] = +{ + { CSERVE2_REQ_FONT_LOAD, SLAVE_FONT, CSERVE2_FONT_LOAD }, + { CSERVE2_REQ_FONT_GLYPHS_LOAD, SLAVE_FONT, CSERVE2_FONT_GLYPHS_LOAD }, + { CSERVE2_REQ_LAST, 0 } +}; + +static Slave *_create_image_slave(void *data); +static Slave *_create_font_slave(void *data); + +static struct _Worker +{ + Slave_Type type; + unsigned int max; + Eina_List *idle; + Eina_List *working; + Slave *(*create_slave)(void *data); +} _workers[] = +{ + { SLAVE_IMAGE, 3, NULL, NULL, _create_image_slave }, + { SLAVE_FONT, 1, NULL, NULL, _create_font_slave }, +}; + +struct _Font_Request +{ Font_Request_Type type; void *data; + void *msg; Eina_List *waiters; Eina_Bool processing; Font_Request_Funcs *funcs; }; -struct _Waiter { +struct _Waiter +{ unsigned int rid; Client *client; }; @@ -78,7 +135,7 @@ cserve2_request_cancel(Font_Request *req, Client *client, Error_Type err) DBG("Removing answer from waiter client: %d, rid: %d", client->id, w->rid); if (req->funcs && req->funcs->error) - req->funcs->error(client, req->data, err); + req->funcs->error(client, req->data, err, w->rid); req->waiters = eina_list_remove_list(req->waiters, l); free(w); } @@ -90,6 +147,7 @@ cserve2_request_cancel(Font_Request *req, Client *client, Error_Type err) { Eina_List **reqlist = &requests[req->type]; *reqlist = eina_list_remove(*reqlist, req); + req->funcs->msg_free(req->msg); free(req); } @@ -107,11 +165,12 @@ cserve2_request_cancel_all(Font_Request *req, Error_Type err) DBG("Removing answer from waiter client: %d, rid: %d", w->client->id, w->rid); if (req->funcs && req->funcs->error) - req->funcs->error(w->client, req->data, err); + req->funcs->error(w->client, req->data, err, w->rid); free(w); } requests[req->type] = eina_list_remove(requests[req->type], req); + req->funcs->msg_free(req->msg); free(req); } @@ -128,3 +187,161 @@ cserve2_requests_shutdown(void) DBG("Shutting down requests."); free(requests); } + +static void +_image_slave_read_cb(Slave *s __UNUSED__, Slave_Command cmd __UNUSED__, void *msg __UNUSED__, void *data __UNUSED__) +{ +} + +static void +_image_slave_dead_cb(Slave *s __UNUSED__, void *data __UNUSED__) +{ +} + +static Slave * +_create_image_slave(void *data) +{ + char *exe; + Slave *slave; + + exe = getenv("EVAS_CSERVE2_SLAVE"); + if (!exe) exe = "evas_cserve2_slave"; + + slave = cserve2_slave_run(exe, _image_slave_read_cb, + _image_slave_dead_cb, data); + + return slave; +} + +static Slave * +_create_font_slave(void *data __UNUSED__) +{ + return NULL; +} + +static Slave_Worker * +_slave_for_request_create(Slave_Type type) +{ + Slave_Worker *sw; + Slave *slave; + + sw = calloc(1, sizeof(Slave_Worker)); + if (!sw) return NULL; + + slave = _workers[type].create_slave(sw); + if (!slave) + { + ERR("Could not launch slave process"); + free(sw); + return NULL; + } + + sw->slave = slave; + _workers[type].idle = eina_list_append(_workers[type].idle, sw); + + return sw; +} + +static Eina_Bool +_cserve2_request_dispatch(Slave_Worker *sw, Message_Type mtype, Font_Request *req) +{ + int size; + char *slave_msg = req->funcs->msg_create(req->data, &size); + + if (!slave_msg) + { + ERR("Could not create slave message for request type %d.", req->type); + return EINA_FALSE; + } + + req->msg = slave_msg; + sw->data = req; + cserve2_slave_send(sw->slave, mtype, slave_msg, size); + req->processing = EINA_TRUE; + + return EINA_TRUE; +} + +static void +_cserve2_request_failed(Font_Request *req, Error_Type type) +{ + Waiter *w; + + EINA_LIST_FREE(req->waiters, w) + { + req->funcs->error(w->client, req->data, type, w->rid); + free(w); + } + + req->funcs->msg_free(req->msg); + free(req); +} + +void +cserve2_requests_process(void) +{ + int rtype, j; + + for (rtype = 0; rtype < CSERVE2_REQ_LAST; rtype++) + { + Slave_Type type = SLAVE_NONE; + Message_Type mtype; + unsigned int max_workers; + Eina_List **idle, **working; + + for (j = 0; _request_match[j].rtype != CSERVE2_REQ_LAST; j++) + { + if (_request_match[j].rtype == j) + { + type = _request_match[j].stype; + mtype = _request_match[j].mtype; + break; + } + } + + if (type == SLAVE_NONE) + continue; + + if (!requests[rtype]) + continue; + + /* Now we have the worker type to use (image or font), and the list + * of requests to process. Just process as many requests as we can. + */ + max_workers = _workers[type].max; + idle = &_workers[type].idle; + working = &_workers[type].working; + + while (requests[j] && + (eina_list_count(*working) < max_workers)) + { + Slave_Worker *sw; + Font_Request *req = eina_list_data_get(requests[rtype]); + requests[rtype] = eina_list_remove_list(requests[rtype], + requests[rtype]); + + if (!(*idle)) + sw = _slave_for_request_create(type); + + if (!(*idle)) + { + ERR("No idle slave available to process request type %d.", + rtype); + _cserve2_request_failed(req, CSERVE2_GENERIC); + continue; + } + + sw = eina_list_data_get(*idle); + if (!_cserve2_request_dispatch(sw, mtype, req)) + { + ERR("Could not dispatch request."); + _cserve2_request_failed(req, CSERVE2_GENERIC); + continue; + } + + *idle = eina_list_remove_list(*idle, *idle); + *working = eina_list_append(*working, sw); + + } + } +}