Wayland generic dispatching API proposal version 2
Kristian Høgsberg
hoegsberg at gmail.com
Tue Jan 15 10:50:26 PST 2013
On Mon, Jan 14, 2013 at 09:34:34PM -0600, Jason Ekstrand wrote:
> Wayland devs:
> A few weeks ago, I sent out a proposal on how we could extend the current
> Wayland API to allow for more general event and request dispatching. I finally
> got around to talking to Kristian about it and some of the ABI issues and
> here's a second version of my proposal. I will also try and organize things a
> bit better.
This looks good, I think you're off in the right direction.
Kristian
> The core of the generic dispatching API would be a dispatcher function of the
> following type:
>
> void wl_libffi_server_dispatcher(struct wl_object * reciever, uint32_t opcode,
> void *client, void *resource, union wl_argument *args);
>
> where wl_argument is given by the following union:
>
> union wl_argument {
> int32_t i;
> uint32_t u;
> wl_fixed_t f;
> const char * s;
> struct wl_object * o;
> uint32_t n;
> struct wl_array * a;
> int32_t h;
> };
>
> The exact meaning of the two void pointer arguments depends on whether the
> dispatcher is for client-side or server-side. On the client side, the first is
> the void pointer given to the library by the client code and the second is the
> server-side object from which the event originates. On the server side, the
> first is a pointer to the wl_client while the second is a pointer to the
> wl_resource.
>
> In order to allow the use of these dispatchers, we would modify wl_interface
> and wl_object in the following way:
>
> struct wl_interface {
> const char *name;
> unt32_t version;
> int method_count;
> const struct wl_message *methods;
> int event_count;
> const struct wl_message *events;
>
> /* Added in version 1 */
> void (*dispatcher)(struct wl_object *, uint32_t, void *, void *,
> union wl_argument *);
> };
>
> struct wl_object {
> const struct wl_interface *interface;
> void *implementation;
> uint32_t id;
> };
>
> First note that I have only made 3 changes:
> * version is now of type int32_t in wl_interface
> * added dispatcher field to the end of wl_interface
> * implementation is now of type void * in wl_object
>
> There would then be a few changes to the semantics of wl_interface.
> Specifically, the version field would now come in two parts: an interface
> version and a struct version. The bottom 16 bits would represent the interface
> version as before while the top 16 bits would represent a structure version
> with the original version of the structure being version 0. In this way, code
> built against the original version of libwayland should not need any
> modification as it should already be setting the version number to something
> sufficiently low that the top 16 bits are zeros. However, of code wishes to
> take advantage of the dispatcher field, it can set the top 16 bits to 1 to
> specify the next version of the structure.
>
> When sending an request (or an event in the client case), libwayland will look
> at the structure version. If the structure version is at least 1, it will look
> at the dispatcher. If the structure version is zero or if the dispatcher is
> null, it will use the default dispatcher that uses libffi and attempt to call a
> function off the C function table provided in the implementation field. If the
> structure version is at least one and the dispatcher is not null, then it will
> attempt to use the provided dispatcher. If it uses an external dispatcher,
> then the implementation field in the wl_object is used by the external
> dispatcher in whatever way it pleases.
>
> Concerning ABI: The only change that should change the layout or packing of any
> of the structures is the addition of the dispatcher field. However, we only
> ever use pointers to wl_interface objects. Because of this, even if the
> wl_interface object is created in client code that is using old header files,
> the dispatcher field should never get accessed as long as version is set
> reasonably.
>
> Added functions: The second part of this proposal is to add a third version to
> each of our sets of variadic functions (such as wl_resource_post_event). Each
> of our variadic functions comes in both a variadic form and one that takes a
> va_args argument. We would add a third version that takes an argument of type
> union wl_argument * to allow for dynamic argument conversion. These functions
> should be fairly simple and straightforward to implement.
>
> There are a couple of specific advantages to adding custom dispatchers. The
> first is that it makes it much easier to write language bindings for dynamic
> languages like Java or Python since you can do argument conversion in a dynamic
> way rather than having to auto-generate the argument conversion code. If, for
> some reason, you wanted to be able to avoid libffi, it is easy to generate a
> dispatcher for a specific C interface. For example, a dispatcher for
> wl_display might look something like this:
>
> void
> wl_shm_pool_dispatcher(struct wl_object *object, uint32_t opcode, void *client,
> void *resource, union wl_argument *args)
> {
> wl_display_interface *impl;
> impl = (wl_display_interface *)object->implementation;
> switch(opcode) {
> case 0:
> (*impl->sync)(client, resource, args[0].n);
> break;
> case 1:
> (*impl->get_registry)(client, resource, args[0].n);
> break;
> }
> }
>
> Please forgive my probably incorrect function pointer casting and calling
> semantics. I haven't tried to compile the above. If you wanted to create a
> dispatcher for a specific implementation of an interface, it could be even
> simpler. This provides at least the possibility of not having to depend on
> libffi.
>
> As always, questions and comments are welcome!
> --Jason Ekstrand
> _______________________________________________
> wayland-devel mailing list
> wayland-devel at lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/wayland-devel
More information about the wayland-devel
mailing list