[PATCH] wl_resource: Add version field and getter/setter
Jason Ekstrand
jason at jlekstrand.net
Thu May 23 13:54:51 PDT 2013
Alex,
Really, this looks like a pretty clean solution. I've spent a fair amount
of time banging around trying to extend wl_resource and this is better than
anything I ever came up with. I only have the one comment (already
mentioned on IRC but repeated here for the sake of the list).
On Thu, May 23, 2013 at 1:28 PM, <alexl at redhat.com> wrote:
> From: Alexander Larsson <alexl at redhat.com>
>
> We create a private structure for extra data and store it in
> a destroy notifier. In this way we can store the version
> in a backwards compatible way.
>
> This lets us track the actual version of a resource which
> is generally the min of what the client requested and what
> the server supports. This will let us avoid sending messages
> the client doesn't support and to not handle requests the
> server doesn't support.
> ---
> src/wayland-server.c | 58
> +++++++++++++++++++++++++++++++++++++++++++++++++++-
> src/wayland-server.h | 6 ++++++
> 2 files changed, 63 insertions(+), 1 deletion(-)
>
> diff --git a/src/wayland-server.c b/src/wayland-server.c
> index a3d3887..c808f6a 100644
> --- a/src/wayland-server.c
> +++ b/src/wayland-server.c
> @@ -102,6 +102,11 @@ struct wl_global {
> struct wl_list link;
> };
>
> +struct wl_resource_private {
> + struct wl_listener listener;
> + uint32_t version;
> +};
> +
> static int wl_debug = 0;
>
> static void
> @@ -377,6 +382,14 @@ WL_EXPORT uint32_t
> wl_client_add_resource(struct wl_client *client,
> struct wl_resource *resource)
> {
> + struct wl_resource_private *priv;
> +
> + priv = calloc(1, sizeof(struct wl_resource_private));
> + if (!priv) {
> + wl_resource_post_no_memory(resource);
> + return 0;
> + }
> +
> if (resource->object.id == 0) {
> resource->object.id =
> wl_map_insert_new(&client->objects,
> @@ -387,12 +400,18 @@ wl_client_add_resource(struct wl_client *client,
> WL_DISPLAY_ERROR_INVALID_OBJECT,
> "invalid new id %d",
> resource->object.id);
> + free(priv);
> return 0;
> }
>
> resource->client = client;
> wl_signal_init(&resource->destroy_signal);
>
> + priv->listener.notify = (wl_notify_func_t)free;
> + wl_signal_add(&resource->destroy_signal, &priv->listener);
> +
> + priv->version = 1;
> +
> return resource->object.id;
> }
>
> @@ -895,6 +914,35 @@ wl_display_get_destroy_listener(struct wl_display
> *display,
> return wl_signal_get(&display->destroy_signal, notify);
> }
>
> +static struct wl_resource_private *
> +wl_resource_get_priv (struct wl_resource *resource)
> +{
> + /* The priv pointer is always the notify handler */
> + return (struct wl_resource_private
> *)resource->destroy_signal.listener_list.next;
> +}
>
wl_signal_get might be better here. It's more robust in (somewhat odd)
case the user code decides to manually put a listener at the beginning.
It's also more readable and almost just as fast (different by an if).
> +
> +WL_EXPORT void
> +wl_resource_set_version(struct wl_resource *resource,
> + uint32_t version)
> +{
> + struct wl_resource_private *priv = wl_resource_get_priv (resource);
> +
> + priv->version = version;
> +}
> +
> +WL_EXPORT uint32_t
> +wl_resource_get_version(struct wl_resource *resource)
> +{
> + struct wl_resource_private *priv = wl_resource_get_priv (resource);
> +
> + return priv->version;
> +}
> +
> +static void
> +dummy_notify(struct wl_listener *listener, void *data)
> +{
> +}
> +
> WL_EXPORT struct wl_resource *
> wl_client_add_object(struct wl_client *client,
> const struct wl_interface *interface,
> @@ -902,8 +950,9 @@ wl_client_add_object(struct wl_client *client,
> uint32_t id, void *data)
> {
> struct wl_resource *resource;
> + struct wl_resource_private *priv;
>
> - resource = malloc(sizeof *resource);
> + resource = malloc(sizeof *resource + sizeof (struct
> wl_resource_private));
> if (resource == NULL) {
> wl_resource_post_no_memory(client->display_resource);
> return NULL;
> @@ -913,6 +962,13 @@ wl_client_add_object(struct wl_client *client,
> resource->client = client;
> resource->destroy = (void *) free;
>
> + priv = (struct wl_resource_private *)(resource + 1);
> +
> + priv->listener.notify = dummy_notify;
> + wl_signal_add(&resource->destroy_signal, &priv->listener);
> +
> + priv->version = 1;
> +
> if (wl_map_insert_at(&client->objects, resource->object.id,
> resource) < 0) {
> wl_resource_post_error(client->display_resource,
> WL_DISPLAY_ERROR_INVALID_OBJECT,
> diff --git a/src/wayland-server.h b/src/wayland-server.h
> index a9cf544..6beb0dd 100644
> --- a/src/wayland-server.h
> +++ b/src/wayland-server.h
> @@ -135,6 +135,12 @@ wl_client_new_object(struct wl_client *client,
> struct wl_resource *
> wl_client_get_object(struct wl_client *client, uint32_t id);
>
> +void
> +wl_resource_set_version(struct wl_resource *resource,
> + uint32_t version);
> +uint32_t
> +wl_resource_get_version(struct wl_resource *resource);
> +
> struct wl_listener {
> struct wl_list link;
> wl_notify_func_t notify;
> --
> 1.8.1.4
>
> _______________________________________________
> wayland-devel mailing list
> wayland-devel at lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/wayland-devel
>
Thanks,
--Jason Ekstrand
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.freedesktop.org/archives/wayland-devel/attachments/20130523/0b2743c8/attachment.html>
More information about the wayland-devel
mailing list