[PATCH v2 wayland 1/3] Track protocol object versions inside wl_proxy.

Derek Foreman derekf at osg.samsung.com
Tue Jan 12 14:28:45 PST 2016


From: Jason Ekstrand <jason at jlekstrand.net>

This provides a standardized mechanism for tracking protocol object
versions in client code.  The wl_display object is created with version 1.
Every time an object is created from within wl_registry_bind, it gets the
bound version.  Every other time an object is created, it simply inherits
it's version from the parent object that created it.

(comments and minor reformatting added
by Derek Foreman <derekf at osg.samsung.com>)

Reviewed-by: Pekka Paalanen <pekka.paalanen at collabora.co.uk>
Signed-off-by: Derek Foreman <derekf at osg.samsung.com>
---
Differences from v1:
Added 3 comments in emit_stubs
Split the function prototype for wl_proxy_marshal_constructor_versioned
 per project coding style

 src/scanner.c             |  34 ++++++++++----
 src/wayland-client-core.h |  15 +++++++
 src/wayland-client.c      | 112 +++++++++++++++++++++++++++++++++++++++++++---
 3 files changed, 146 insertions(+), 15 deletions(-)

diff --git a/src/scanner.c b/src/scanner.c
index b00f036..1d626f4 100644
--- a/src/scanner.c
+++ b/src/scanner.c
@@ -956,6 +956,14 @@ emit_stubs(struct wl_list *message_list, struct interface *interface)
 	       interface->name, interface->name, interface->name,
 	       interface->name);
 
+	printf("static inline uint32_t\n"
+	       "%s_get_version(struct %s *%s)\n"
+	       "{\n"
+	       "\treturn wl_proxy_get_version((struct wl_proxy *) %s);\n"
+	       "}\n\n",
+	       interface->name, interface->name, interface->name,
+	       interface->name);
+
 	has_destructor = 0;
 	has_destroy = 0;
 	wl_list_for_each(m, message_list, link) {
@@ -1027,21 +1035,31 @@ emit_stubs(struct wl_list *message_list, struct interface *interface)
 
 		printf(")\n"
 		       "{\n");
-		if (ret) {
+		if (ret && ret->interface_name == NULL) {
+			/* an arg has type ="new_id" but interface is not
+			 * provided, such as in wl_registry.bind */
 			printf("\tstruct wl_proxy *%s;\n\n"
-			       "\t%s = wl_proxy_marshal_constructor("
+			       "\t%s = wl_proxy_marshal_constructor_versioned("
 			       "(struct wl_proxy *) %s,\n"
-			       "\t\t\t %s_%s, ",
+			       "\t\t\t %s_%s, interface, version",
 			       ret->name, ret->name,
 			       interface->name,
 			       interface->uppercase_name,
 			       m->uppercase_name);
-
-			if (ret->interface_name == NULL)
-				printf("interface");
-			else
-				printf("&%s_interface", ret->interface_name);
+		} else if (ret) {
+			/* Normal factory case, an arg has type="new_id" and
+			 * an interface is provided */
+			printf("\tstruct wl_proxy *%s;\n\n"
+			       "\t%s = wl_proxy_marshal_constructor("
+			       "(struct wl_proxy *) %s,\n"
+			       "\t\t\t %s_%s, &%s_interface",
+			       ret->name, ret->name,
+			       interface->name,
+			       interface->uppercase_name,
+			       m->uppercase_name,
+			       ret->interface_name);
 		} else {
+			/* No args have type="new_id" */
 			printf("\twl_proxy_marshal((struct wl_proxy *) %s,\n"
 			       "\t\t\t %s_%s",
 			       interface->name,
diff --git a/src/wayland-client-core.h b/src/wayland-client-core.h
index a729395..91f7e7b 100644
--- a/src/wayland-client-core.h
+++ b/src/wayland-client-core.h
@@ -139,9 +139,21 @@ wl_proxy_marshal_constructor(struct wl_proxy *proxy,
 			     ...);
 
 struct wl_proxy *
+wl_proxy_marshal_constructor_versioned(struct wl_proxy *proxy,
+				       uint32_t opcode,
+				       const struct wl_interface *interface,
+				       uint32_t version,
+				       ...);
+struct wl_proxy *
 wl_proxy_marshal_array_constructor(struct wl_proxy *proxy,
 				   uint32_t opcode, union wl_argument *args,
 				   const struct wl_interface *interface);
+struct wl_proxy *
+wl_proxy_marshal_array_constructor_versioned(struct wl_proxy *proxy,
+					     uint32_t opcode,
+					     union wl_argument *args,
+					     const struct wl_interface *interface,
+					     uint32_t version);
 
 void
 wl_proxy_destroy(struct wl_proxy *proxy);
@@ -165,6 +177,9 @@ void *
 wl_proxy_get_user_data(struct wl_proxy *proxy);
 
 uint32_t
+wl_proxy_get_version(struct wl_proxy *proxy);
+
+uint32_t
 wl_proxy_get_id(struct wl_proxy *proxy);
 
 const char *
diff --git a/src/wayland-client.c b/src/wayland-client.c
index 2796030..d935f6c 100644
--- a/src/wayland-client.c
+++ b/src/wayland-client.c
@@ -62,6 +62,7 @@ struct wl_proxy {
 	int refcount;
 	void *user_data;
 	wl_dispatcher_func_t dispatcher;
+	uint32_t version;
 };
 
 struct wl_global {
@@ -326,7 +327,8 @@ wl_display_create_queue(struct wl_display *display)
 }
 
 static struct wl_proxy *
-proxy_create(struct wl_proxy *factory, const struct wl_interface *interface)
+proxy_create(struct wl_proxy *factory, const struct wl_interface *interface,
+	     uint32_t version)
 {
 	struct wl_proxy *proxy;
 	struct wl_display *display = factory->display;
@@ -339,6 +341,7 @@ proxy_create(struct wl_proxy *factory, const struct wl_interface *interface)
 	proxy->display = display;
 	proxy->queue = factory->queue;
 	proxy->refcount = 1;
+	proxy->version = version;
 
 	proxy->object.id = wl_map_insert_new(&display->objects, 0, proxy);
 
@@ -371,7 +374,7 @@ wl_proxy_create(struct wl_proxy *factory, const struct wl_interface *interface)
 	struct wl_proxy *proxy;
 
 	pthread_mutex_lock(&display->mutex);
-	proxy = proxy_create(factory, interface);
+	proxy = proxy_create(factory, interface, factory->version);
 	pthread_mutex_unlock(&display->mutex);
 
 	return proxy;
@@ -394,6 +397,7 @@ wl_proxy_create_for_id(struct wl_proxy *factory,
 	proxy->display = display;
 	proxy->queue = factory->queue;
 	proxy->refcount = 1;
+	proxy->version = factory->version;
 
 	wl_map_insert_at(&display->objects, 0, id, proxy);
 
@@ -525,7 +529,7 @@ wl_proxy_add_dispatcher(struct wl_proxy *proxy,
 static struct wl_proxy *
 create_outgoing_proxy(struct wl_proxy *proxy, const struct wl_message *message,
 		      union wl_argument *args,
-		      const struct wl_interface *interface)
+		      const struct wl_interface *interface, uint32_t version)
 {
 	int i, count;
 	const char *signature;
@@ -539,7 +543,7 @@ create_outgoing_proxy(struct wl_proxy *proxy, const struct wl_message *message,
 
 		switch (arg.type) {
 		case 'n':
-			new_proxy = proxy_create(proxy, interface);
+			new_proxy = proxy_create(proxy, interface, version);
 			if (new_proxy == NULL)
 				return NULL;
 
@@ -564,7 +568,8 @@ create_outgoing_proxy(struct wl_proxy *proxy, const struct wl_message *message,
  *
  * For new-id arguments, this function will allocate a new wl_proxy
  * and send the ID to the server.  The new wl_proxy will be returned
- * on success or NULL on errror with errno set accordingly.
+ * on success or NULL on errror with errno set accordingly.  The newly
+ * created proxy will inherit their version from their parent.
  *
  * \note This is intended to be used by language bindings and not in
  * non-generated code.
@@ -578,6 +583,43 @@ wl_proxy_marshal_array_constructor(struct wl_proxy *proxy,
 				   uint32_t opcode, union wl_argument *args,
 				   const struct wl_interface *interface)
 {
+	return wl_proxy_marshal_array_constructor_versioned(proxy, opcode,
+							    args, interface,
+							    proxy->version);
+}
+
+
+/** Prepare a request to be sent to the compositor
+ *
+ * \param proxy The proxy object
+ * \param opcode Opcode of the request to be sent
+ * \param args Extra arguments for the given request
+ * \param interface The interface to use for the new proxy
+ * \param version The protocol object version for the new proxy
+ *
+ * Translates the request given by opcode and the extra arguments into the
+ * wire format and write it to the connection buffer.  This version takes an
+ * array of the union type wl_argument.
+ *
+ * For new-id arguments, this function will allocate a new wl_proxy
+ * and send the ID to the server.  The new wl_proxy will be returned
+ * on success or NULL on errror with errno set accordingly.  The newly
+ * created proxy will have the version specified.
+ *
+ * \note This is intended to be used by language bindings and not in
+ * non-generated code.
+ *
+ * \sa wl_proxy_marshal()
+ *
+ * \memberof wl_proxy
+ */
+WL_EXPORT struct wl_proxy *
+wl_proxy_marshal_array_constructor_versioned(struct wl_proxy *proxy,
+					     uint32_t opcode,
+					     union wl_argument *args,
+					     const struct wl_interface *interface,
+					     uint32_t version)
+{
 	struct wl_closure *closure;
 	struct wl_proxy *new_proxy = NULL;
 	const struct wl_message *message;
@@ -587,7 +629,8 @@ wl_proxy_marshal_array_constructor(struct wl_proxy *proxy,
 	message = &proxy->object.interface->methods[opcode];
 	if (interface) {
 		new_proxy = create_outgoing_proxy(proxy, message,
-						  args, interface);
+						  args, interface,
+						  version);
 		if (new_proxy == NULL)
 			goto err_unlock;
 	}
@@ -655,7 +698,8 @@ wl_proxy_marshal(struct wl_proxy *proxy, uint32_t opcode, ...)
  *
  * For new-id arguments, this function will allocate a new wl_proxy
  * and send the ID to the server.  The new wl_proxy will be returned
- * on success or NULL on errror with errno set accordingly.
+ * on success or NULL on errror with errno set accordingly.  The newly
+ * created proxy will inherit their version from their parent.
  *
  * \note This should not normally be used by non-generated code.
  *
@@ -677,6 +721,46 @@ wl_proxy_marshal_constructor(struct wl_proxy *proxy, uint32_t opcode,
 						  args, interface);
 }
 
+
+/** Prepare a request to be sent to the compositor
+ *
+ * \param proxy The proxy object
+ * \param opcode Opcode of the request to be sent
+ * \param interface The interface to use for the new proxy
+ * \param version The protocol object version of the new proxy
+ * \param ... Extra arguments for the given request
+ * \return A new wl_proxy for the new_id argument or NULL on error
+ *
+ * Translates the request given by opcode and the extra arguments into the
+ * wire format and write it to the connection buffer.
+ *
+ * For new-id arguments, this function will allocate a new wl_proxy
+ * and send the ID to the server.  The new wl_proxy will be returned
+ * on success or NULL on errror with errno set accordingly.  The newly
+ * created proxy will have the version specified.
+ *
+ * \note This should not normally be used by non-generated code.
+ *
+ * \memberof wl_proxy
+ */
+WL_EXPORT struct wl_proxy *
+wl_proxy_marshal_constructor_versioned(struct wl_proxy *proxy, uint32_t opcode,
+				       const struct wl_interface *interface,
+				       uint32_t version, ...)
+{
+	union wl_argument args[WL_CLOSURE_MAX_ARGS];
+	va_list ap;
+
+	va_start(ap, version);
+	wl_argument_from_va_list(proxy->object.interface->methods[opcode].signature,
+				 args, WL_CLOSURE_MAX_ARGS, ap);
+	va_end(ap);
+
+	return wl_proxy_marshal_array_constructor_versioned(proxy, opcode,
+							    args, interface,
+							    version);
+}
+
 /** Prepare a request to be sent to the compositor
  *
  * \param proxy The proxy object
@@ -838,6 +922,7 @@ wl_display_connect_to_fd(int fd)
 	display->proxy.queue = &display->default_queue;
 	display->proxy.flags = 0;
 	display->proxy.refcount = 1;
+	display->proxy.version = 1;
 
 	display->connection = wl_connection_create(display->fd);
 	if (display->connection == NULL)
@@ -1829,6 +1914,19 @@ wl_proxy_get_user_data(struct wl_proxy *proxy)
 	return proxy->user_data;
 }
 
+/** Get the protocol object version of a proxy object
+ *
+ * \param proxy The proxy object
+ * \return The protocol object version of the proxy
+ *
+ * \memberof wl_proxy
+ */
+WL_EXPORT uint32_t
+wl_proxy_get_version(struct wl_proxy *proxy)
+{
+	return proxy->version;
+}
+
 /** Get the id of a proxy object
  *
  * \param proxy The proxy object
-- 
2.6.4



More information about the wayland-devel mailing list