5 #include "evas_cserve2.h"
26 typedef struct _Slave_Worker Slave_Worker;
28 /* This struct is used to match font request types to the respective slave
29 * type, and the message type that will be used for that request. The order
30 * of the request types on it is the order in which these requests will
33 static struct _Request_Match
35 Font_Request_Type rtype;
40 { CSERVE2_REQ_FONT_LOAD, SLAVE_FONT, CSERVE2_FONT_LOAD },
41 { CSERVE2_REQ_FONT_GLYPHS_LOAD, SLAVE_FONT, CSERVE2_FONT_GLYPHS_LOAD },
42 { CSERVE2_REQ_LAST, 0 }
45 static Slave *_create_image_slave(void *data);
46 static Slave *_create_font_slave(void *data);
54 Slave *(*create_slave)(void *data);
57 { SLAVE_IMAGE, 3, NULL, NULL, _create_image_slave },
58 { SLAVE_FONT, 1, NULL, NULL, _create_font_slave },
63 Font_Request_Type type;
68 Font_Request_Funcs *funcs;
77 typedef struct _Waiter Waiter;
79 static Eina_List **requests = NULL;
82 _request_waiter_add(Font_Request *req, Client *client, unsigned int rid)
84 Waiter *w = malloc(sizeof(*w));
86 DBG("Add waiter to request. Client: %d, rid: %d", client->id, rid);
91 req->waiters = eina_list_append(req->waiters, w);
95 cserve2_request_add(Font_Request_Type type, unsigned int rid, Client *client, Font_Request_Funcs *funcs, void *data)
97 Font_Request *req, *r;
101 EINA_LIST_FOREACH(requests[type], l, r)
112 DBG("Add request for rid: %d", rid);
113 req = malloc(sizeof(*req));
116 req->processing = EINA_FALSE;
117 requests[type] = eina_list_append(requests[type], req);
120 _request_waiter_add(req, client, rid);
126 cserve2_request_cancel(Font_Request *req, Client *client, Error_Type err)
128 Eina_List *l, *l_next;
131 EINA_LIST_FOREACH_SAFE(req->waiters, l, l_next, w)
133 if (w->client->id == client->id)
135 DBG("Removing answer from waiter client: %d, rid: %d",
137 if (req->funcs && req->funcs->error)
138 req->funcs->error(client, req->data, err, w->rid);
139 req->waiters = eina_list_remove_list(req->waiters, l);
144 // TODO: When we have speculative preload, there may be no waiters,
145 // so we need a flag or something else to make things still load.
148 Eina_List **reqlist = &requests[req->type];
149 *reqlist = eina_list_remove(*reqlist, req);
150 req->funcs->msg_free(req->msg);
157 cserve2_request_cancel_all(Font_Request *req, Error_Type err)
161 DBG("Removing all answers.");
163 EINA_LIST_FREE(req->waiters, w)
165 DBG("Removing answer from waiter client: %d, rid: %d",
166 w->client->id, w->rid);
167 if (req->funcs && req->funcs->error)
168 req->funcs->error(w->client, req->data, err, w->rid);
172 requests[req->type] = eina_list_remove(requests[req->type], req);
173 req->funcs->msg_free(req->msg);
178 cserve2_requests_init(void)
180 DBG("Initializing requests.");
181 requests = calloc(CSERVE2_REQ_LAST, sizeof(Eina_List *));
185 cserve2_requests_shutdown(void)
187 DBG("Shutting down requests.");
192 _image_slave_read_cb(Slave *s __UNUSED__, Slave_Command cmd __UNUSED__, void *msg __UNUSED__, void *data __UNUSED__)
197 _image_slave_dead_cb(Slave *s __UNUSED__, void *data __UNUSED__)
202 _create_image_slave(void *data)
207 exe = getenv("EVAS_CSERVE2_SLAVE");
208 if (!exe) exe = "evas_cserve2_slave";
210 slave = cserve2_slave_run(exe, _image_slave_read_cb,
211 _image_slave_dead_cb, data);
217 _create_font_slave(void *data __UNUSED__)
222 static Slave_Worker *
223 _slave_for_request_create(Slave_Type type)
228 sw = calloc(1, sizeof(Slave_Worker));
229 if (!sw) return NULL;
231 slave = _workers[type].create_slave(sw);
234 ERR("Could not launch slave process");
240 _workers[type].idle = eina_list_append(_workers[type].idle, sw);
246 _cserve2_request_dispatch(Slave_Worker *sw, Message_Type mtype, Font_Request *req)
249 char *slave_msg = req->funcs->msg_create(req->data, &size);
253 ERR("Could not create slave message for request type %d.", req->type);
257 req->msg = slave_msg;
259 cserve2_slave_send(sw->slave, mtype, slave_msg, size);
260 req->processing = EINA_TRUE;
266 _cserve2_request_failed(Font_Request *req, Error_Type type)
270 EINA_LIST_FREE(req->waiters, w)
272 req->funcs->error(w->client, req->data, type, w->rid);
276 req->funcs->msg_free(req->msg);
281 cserve2_requests_process(void)
285 for (rtype = 0; rtype < CSERVE2_REQ_LAST; rtype++)
287 Slave_Type type = SLAVE_NONE;
289 unsigned int max_workers;
290 Eina_List **idle, **working;
292 for (j = 0; _request_match[j].rtype != CSERVE2_REQ_LAST; j++)
294 if (_request_match[j].rtype == j)
296 type = _request_match[j].stype;
297 mtype = _request_match[j].mtype;
302 if (type == SLAVE_NONE)
305 if (!requests[rtype])
308 /* Now we have the worker type to use (image or font), and the list
309 * of requests to process. Just process as many requests as we can.
311 max_workers = _workers[type].max;
312 idle = &_workers[type].idle;
313 working = &_workers[type].working;
315 while (requests[j] &&
316 (eina_list_count(*working) < max_workers))
319 Font_Request *req = eina_list_data_get(requests[rtype]);
320 requests[rtype] = eina_list_remove_list(requests[rtype],
324 sw = _slave_for_request_create(type);
328 ERR("No idle slave available to process request type %d.",
330 _cserve2_request_failed(req, CSERVE2_GENERIC);
334 sw = eina_list_data_get(*idle);
335 if (!_cserve2_request_dispatch(sw, mtype, req))
337 ERR("Could not dispatch request.");
338 _cserve2_request_failed(req, CSERVE2_GENERIC);
342 *idle = eina_list_remove_list(*idle, *idle);
343 *working = eina_list_append(*working, sw);