evas/cserve2: Add requests and slave workers

management.



SVN revision: 71601
This commit is contained in:
Rafael Antognolli 2012-05-31 21:33:59 +00:00
parent 2c9e6a10f3
commit a3fa30f70b
2 changed files with 226 additions and 7 deletions

View File

@ -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;
};

View File

@ -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);
}
}
}