diff options
author | Kristian Høgsberg <krh@bitplanet.net> | 2013-11-14 21:29:06 -0800 |
---|---|---|
committer | Kristian Høgsberg <krh@bitplanet.net> | 2013-11-14 21:29:06 -0800 |
commit | 00345b3b4a0b48fc83920e25f38fb50c2115d491 (patch) | |
tree | d3e5fc910be3eb507f60a25ba06acf6b6ad63b0f | |
parent | 05f95c85c8cad07bee233f1d4e205a12538365e1 (diff) |
proxy race fixproxy-race
-rw-r--r-- | src/scanner.c | 36 | ||||
-rw-r--r-- | src/wayland-client.c | 111 | ||||
-rw-r--r-- | src/wayland-client.h | 4 |
3 files changed, 109 insertions, 42 deletions
diff --git a/src/scanner.c b/src/scanner.c index 0fbaabd..44f7d6d 100644 --- a/src/scanner.c +++ b/src/scanner.c @@ -654,31 +654,31 @@ emit_stubs(struct wl_list *message_list, struct interface *interface) "{\n"); if (ret) { printf("\tstruct wl_proxy *%s;\n\n" - "\t%s = wl_proxy_create(" - "(struct wl_proxy *) %s,\n", - ret->name, ret->name, interface->name); + "\t%s = wl_proxy_marshal_constructor(" + "(struct wl_proxy *) %s,\n" + "\t\t\t %s_%s, ", + ret->name, ret->name, + interface->name, + interface->uppercase_name, + m->uppercase_name); + if (ret->interface_name == NULL) - printf("\t\t\t interface);\n"); + printf("interface"); else - printf("\t\t\t &%s_interface);\n", - ret->interface_name); - - printf("\tif (!%s)\n" - "\t\treturn NULL;\n\n", - ret->name); + printf("&%s_interface", ret->interface_name); + } else { + printf("\twl_proxy_marshal((struct wl_proxy *) %s,\n" + "\t\t\t %s_%s", + interface->name, + interface->uppercase_name, + m->uppercase_name); } - printf("\twl_proxy_marshal((struct wl_proxy *) %s,\n" - "\t\t\t %s_%s", - interface->name, - interface->uppercase_name, - m->uppercase_name); - wl_list_for_each(a, &m->arg_list, link) { if (a->type == NEW_ID && a->interface_name == NULL) printf(", interface->name, version"); - printf(", "); - printf("%s", a->name); + else if (a->type != NEW_ID) + printf(", %s", a->name); } printf(");\n"); diff --git a/src/wayland-client.c b/src/wayland-client.c index e92317a..5118004 100644 --- a/src/wayland-client.c +++ b/src/wayland-client.c @@ -382,6 +382,76 @@ wl_proxy_add_dispatcher(struct wl_proxy *proxy, return 0; } +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) +{ + int i, count; + const char *signature; + struct argument_details arg; + struct wl_proxy *new_proxy = NULL; + + count = arg_count_for_signature(message->signature); + signature = message->signature; + for (i = 0; i < count; i++) { + signature = get_next_argument(signature, &arg); + + switch (arg.type) { + case 'n': + new_proxy = wl_proxy_create(proxy, interface); + if (new_proxy == NULL) + return NULL; + + args[i].n = proxy->object.id; + break; + } + } + + return new_proxy; +} + +static struct wl_proxy * +proxy_marshal_array(struct wl_proxy *proxy, + uint32_t opcode, union wl_argument *args, + const struct wl_interface *interface) +{ + struct wl_closure *closure; + struct wl_proxy *new_proxy = NULL; + const struct wl_message *message; + + pthread_mutex_lock(&proxy->display->mutex); + + message = &proxy->object.interface->methods[opcode]; + if (interface) { + new_proxy = create_outgoing_proxy(proxy, message, + args, interface); + if (new_proxy == NULL) + return NULL; + } + + closure = wl_closure_marshal(&proxy->object, opcode, args, message); + if (closure == NULL) { + fprintf(stderr, "Error marshalling request\n"); + abort(); + } + + if (wl_debug) + wl_closure_print(closure, &proxy->object, true); + + if (wl_closure_send(closure, proxy->display->connection)) { + fprintf(stderr, "Error sending request: %m\n"); + abort(); + } + + wl_closure_destroy(closure); + + pthread_mutex_unlock(&proxy->display->mutex); + + return new_proxy; +} + + /** Prepare a request to be sent to the compositor * * \param proxy The proxy object @@ -421,7 +491,22 @@ wl_proxy_marshal(struct wl_proxy *proxy, uint32_t opcode, ...) args, WL_CLOSURE_MAX_ARGS, ap); va_end(ap); - wl_proxy_marshal_array(proxy, opcode, args); + proxy_marshal_array(proxy, opcode, args, NULL); +} + +WL_EXPORT struct wl_proxy * +wl_proxy_marshal_constructor(struct wl_proxy *proxy, uint32_t opcode, + const struct wl_interface *interface, ...) +{ + union wl_argument args[WL_CLOSURE_MAX_ARGS]; + va_list ap; + + va_start(ap, interface); + wl_argument_from_va_list(proxy->object.interface->methods[opcode].signature, + args, WL_CLOSURE_MAX_ARGS, ap); + va_end(ap); + + return proxy_marshal_array(proxy, opcode, args, interface); } /** Prepare a request to be sent to the compositor @@ -445,29 +530,7 @@ WL_EXPORT void wl_proxy_marshal_array(struct wl_proxy *proxy, uint32_t opcode, union wl_argument *args) { - struct wl_closure *closure; - - pthread_mutex_lock(&proxy->display->mutex); - - closure = wl_closure_marshal(&proxy->object, opcode, args, - &proxy->object.interface->methods[opcode]); - - if (closure == NULL) { - fprintf(stderr, "Error marshalling request\n"); - abort(); - } - - if (wl_debug) - wl_closure_print(closure, &proxy->object, true); - - if (wl_closure_send(closure, proxy->display->connection)) { - fprintf(stderr, "Error sending request: %m\n"); - abort(); - } - - wl_closure_destroy(closure); - - pthread_mutex_unlock(&proxy->display->mutex); + proxy_marshal_array(proxy, opcode, args, NULL); } static void diff --git a/src/wayland-client.h b/src/wayland-client.h index 43ba3fc..4b19aef 100644 --- a/src/wayland-client.h +++ b/src/wayland-client.h @@ -126,6 +126,10 @@ void wl_proxy_marshal_array(struct wl_proxy *p, uint32_t opcode, union wl_argument *args); struct wl_proxy *wl_proxy_create(struct wl_proxy *factory, const struct wl_interface *interface); +struct wl_proxy *wl_proxy_marshal_constructor(struct wl_proxy *proxy, + uint32_t opcode, + const struct wl_interface *interface, + ...); void wl_proxy_destroy(struct wl_proxy *proxy); int wl_proxy_add_listener(struct wl_proxy *proxy, |