[Xcb] ecore and xcb: looking for advices.
Vincent Torri
vtorri at univ-evry.fr
Sun Mar 4 23:25:41 PST 2007
Hey,
>> 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.
ok
>> * 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;
};
or
struct Ecore_Xcb_Get_XY_Args
{
xcb_window_t win;
};
That data is allocated in the _prefetch functions. Hence:
ecore_x_pointer_xy_get_prefetch(win)
{
Ecore_Xcb_Get_XY_Args *args;
allocate(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
free(reply)
}
_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
below).
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
Vincent
More information about the Xcb
mailing list