[Xcb] ecore and xcb: looking for advices.

Vincent Torri vtorri at univ-evry.fr
Sun Mar 4 23:25:41 PST 2007


>> I've written an xcb port of ecore_x, and it mainly wraps xcb. Problem: its 
>> api is quite different from the one of ecore_x, and raster would prefer to 
>> keep ecore_x api. His point is: we add some functions specific to xcb (the 
>> methods that send the requests, and maybe some functions to get/free the 
>> replies). The advantage: modifying programs (mainly e17 and toolkits like 
>> etk or ewl) would be a minor tasks: we send all the needed requests (with 
>> the added methods), we use the current ecore_x methods (with the modified 
>> ecore_x methods, which would get the replies), and we free the replies with 
>> the added methods.
> It sounds like raster wants to ensure current code still works. In other 
> words, ecore_xcb would support the xlib synchronous API as well as extra xcb 
> asynchronous methods.  I think that is a worthwhile goal.
>> Simple example with current code:
>>   ecore_x_pointer_xy_get(win, &x1, &y1);
>>   atom = ecore_x_atom_get("toto");
>> Wanted code:
>>   /* added functions: we send all the needed requests */
>>   ecore_x_pointer_xy_get_request(win);
>>   ecore_x_atom_get_request("toto");
>>   /* existing but modified functions: we get the replies */
>>   ecore_x_pointer_xy_get(win, &x1, &y1);
>>   atom = ecore_x_atom_get("toto");
> Seems good so far.  (XCB uses the word "prefetch" for the first call for 
> similar cases, such as extension data.)

ok. Maybe I'll use prefetch, to have an api consistent with xcb one

>>   /* added functions: we free the replies */
>>   ecore_x_pointer_xy_get_free(win);
>>   ecore_x_atom_get_free(atom);
> I don't think these would be necessary. Request cleanup would happen when you 
> get the results.  It might mean a little extra copying if you return pointers 
> directly into replys.


>> * ecore_x_pointer_xy_get_request and ecore_x_atom_get_request would store 
>> the cookie and a pointer to the corresponding reply function, in an array. 
>> The size of the array is not huge. Except the initialization of 
>> ecore_x(cb), I think that sending more than 16 requests is quite rare. If 
>> so, I will set the size of the array to 16. If more than 16 requests are 
>> sent, I will resize the array.
>> * ecore_x_pointer_xy_get and ecore_x_atom_get would call the reply of each 
>> requests in the above array. Hence some of their arguments would be 
>> useless. Of course, in that design, the order of the calls is important.
>> * the *_free functions would just be one function, actually. It would just 
>> free all the replies available in the array.
> I don't think storing the reply function pointer will be good enough, because 
> you also need all the type information and request parameters that go along 
> with it. I'm guessing what you really need to use is your own cache key based 
> on both the request and the parameters (not so simple). What if the caller 
> wants to get a bunch of atoms at once? There will be several atom_get cookies 
> in your cache, each with different parameters.
> So your reply cache interface would have to look something like this 
> pseudocode:
> ecore_x_pointer_xy_get_request(win)
> {
> 	key = { ECORE_XCB_GET_XY, win }
> 	cookie = xcb_get_xy(conn, win)
> 	_cache_cookie(key, cookie)
> }
> ecore_x_pointer_xy_get(win, *x, *y)
> {
> 	key = { ECORE_XCB_GET_XY, win }
> 	cookie = _uncache_cookie(key)
> 	if (!cookie)
> 		cookie = xcb_get_xy(conn, win)	// synchronous: old Xlib 
> behaviour
> 	reply = xcb_get_xy_reply(cookie)
> 	*x = reply->x
> 	*y = reply->y
> 	free(reply)
> }
> This shows that the parameters you thought were useless actually *are* used 
> to distinguish between the cookies from multiple requests.

ok for the parameters. I've forgotten that :).

> The hard part is figuring out an efficient way to construct and use these 
> cache keys, since the parameters to each request are different.

I don't see the interest of having a ECORE_XCB_GET_XY in the key. I would 
see something like that :

struct Ecore_Xcb_Data
   unsigned int cookie;
   void *args;

Ecore_Xcb_Data is a data that I store in a queue (as you told me on IRC). 
And internally, for each function that need it, I declare a structure that 
correspond to the args. Like

struct Ecore_Xcb_Atom_Args
   char *atom_name;


struct Ecore_Xcb_Get_XY_Args
   xcb_window_t win;

That data is allocated in the _prefetch functions. Hence:

       Ecore_Xcb_Get_XY_Args *args;

       args->win = win;
       cookie = xcb_get_xy(conn, win)
       _cache_cookie(args, cookie)

_cache_cookie would store args and cookie in a Ecore_Xcb_Data.

ecore_x_pointer_xy_get(win, *x, *y)
       Ecore_Xcb_Get_XY_Args *args;

       cookie = _uncache_cookie(&args)
       if (!cookie)
               cookie = xcb_get_xy(conn, win)  // synchronous: old Xlib behaviour
       reply = xcb_get_xy_reply(cookie)
       *x = reply->x
       *y = reply->y

_uncache_cookie would just take the first element of the queue. Of course, 
that means that the user must ask for the replies in the correct order, 
and must not send a request without asking for the reply (as you said 

So, I don't need a key like ECORE_XCB_GET_XY, as you mentioned. Do I miss 
something ?

> Another corner case: what if the user calls *_request and doesn't actually 
> get the reply? Need some way to expire stuff out of the cache.

It's up to the user (in that case raster) to not be stupid. I think I can 
trust him :-D

Another question: ecore has a list that can be used as a queue: it can 
adds elements at the end of the list, and remove elements at the beginning 
of the list (like a fifo queue). But maybe a list is a bit slow, compared 
to an array. As I said, except for the initialization of ecore (where 
there is ~250 requests/replies, and which will be written with xcb only), 
there will not be a lot of requests simutaneously.
So, in that case, should I use an array instead of a list ?

Thank you


More information about the Xcb mailing list