mirror of
				https://gitlab.freedesktop.org/wayland/wayland.git
				synced 2025-11-03 09:01:42 -05:00 
			
		
		
		
	client: Split event handling into demarshal and dispatch steps
This lets us demarshal with a mutex held and then do dispatching after releasing the mutex.
This commit is contained in:
		
							parent
							
								
									53d24713a3
								
							
						
					
					
						commit
						ce1f4c29ab
					
				
					 2 changed files with 49 additions and 20 deletions
				
			
		| 
						 | 
					@ -499,22 +499,29 @@ create_proxies(struct wl_display *display, struct wl_closure *closure)
 | 
				
			||||||
	return 0;
 | 
						return 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void
 | 
					static int
 | 
				
			||||||
handle_event(struct wl_display *display,
 | 
					queue_event(struct wl_display *display, int len, struct wl_list *list)
 | 
				
			||||||
	     uint32_t id, uint32_t opcode, uint32_t size)
 | 
					 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
 | 
						uint32_t p[2], id;
 | 
				
			||||||
 | 
						int opcode, size;
 | 
				
			||||||
	struct wl_proxy *proxy;
 | 
						struct wl_proxy *proxy;
 | 
				
			||||||
	struct wl_closure *closure;
 | 
						struct wl_closure *closure;
 | 
				
			||||||
	const struct wl_message *message;
 | 
						const struct wl_message *message;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	proxy = wl_map_lookup(&display->objects, id);
 | 
						wl_connection_copy(display->connection, p, sizeof p);
 | 
				
			||||||
 | 
						id = p[0];
 | 
				
			||||||
 | 
						opcode = p[1] & 0xffff;
 | 
				
			||||||
 | 
						size = p[1] >> 16;
 | 
				
			||||||
 | 
						if (len < size)
 | 
				
			||||||
 | 
							return 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						proxy = wl_map_lookup(&display->objects, id);
 | 
				
			||||||
	if (proxy == WL_ZOMBIE_OBJECT) {
 | 
						if (proxy == WL_ZOMBIE_OBJECT) {
 | 
				
			||||||
		wl_connection_consume(display->connection, size);
 | 
							wl_connection_consume(display->connection, size);
 | 
				
			||||||
		return;
 | 
							return size;
 | 
				
			||||||
	} else if (proxy == NULL || proxy->object.implementation == NULL) {
 | 
						} else if (proxy == NULL || proxy->object.implementation == NULL) {
 | 
				
			||||||
		wl_connection_consume(display->connection, size);
 | 
							wl_connection_consume(display->connection, size);
 | 
				
			||||||
		return;
 | 
							return size;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	message = &proxy->object.interface->events[opcode];
 | 
						message = &proxy->object.interface->events[opcode];
 | 
				
			||||||
| 
						 | 
					@ -529,40 +536,61 @@ handle_event(struct wl_display *display,
 | 
				
			||||||
		abort();
 | 
							abort();
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						wl_list_insert(list->prev, &closure->link);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return size;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void
 | 
				
			||||||
 | 
					dispatch_event(struct wl_display *display, struct wl_closure *closure)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct wl_proxy *proxy;
 | 
				
			||||||
 | 
						uint32_t id;
 | 
				
			||||||
 | 
						int opcode;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						wl_list_remove(&closure->link);
 | 
				
			||||||
 | 
						id = closure->buffer[0];
 | 
				
			||||||
 | 
						opcode = closure->buffer[1] & 0xffff;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						proxy = wl_map_lookup(&display->objects, id);
 | 
				
			||||||
 | 
						if (proxy == WL_ZOMBIE_OBJECT)
 | 
				
			||||||
 | 
							goto skip;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	wl_closure_invoke(closure, &proxy->object,
 | 
						wl_closure_invoke(closure, &proxy->object,
 | 
				
			||||||
			  proxy->object.implementation[opcode],
 | 
								  proxy->object.implementation[opcode],
 | 
				
			||||||
			  proxy->user_data);
 | 
								  proxy->user_data);
 | 
				
			||||||
 | 
					 skip:
 | 
				
			||||||
	wl_closure_destroy(closure);
 | 
						wl_closure_destroy(closure);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
WL_EXPORT int
 | 
					WL_EXPORT int
 | 
				
			||||||
wl_display_dispatch(struct wl_display *display)
 | 
					wl_display_dispatch(struct wl_display *display)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	uint32_t p[2], object;
 | 
						struct wl_list list;
 | 
				
			||||||
	int len, opcode, size;
 | 
						struct wl_closure *closure;
 | 
				
			||||||
 | 
						int len, size;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* FIXME: Handle flush errors, EAGAIN... */
 | 
						/* FIXME: Handle flush errors, EAGAIN... */
 | 
				
			||||||
	wl_display_flush(display);
 | 
						wl_display_flush(display);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* FIXME: Shouldn't always read here... */
 | 
						/* FIXME: Shouldn't always read here... */
 | 
				
			||||||
	len = wl_connection_read(display->connection);
 | 
						len = wl_connection_read(display->connection);
 | 
				
			||||||
 | 
						if (len == -1)
 | 
				
			||||||
 | 
							return -1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	while (len > 0) {
 | 
						wl_list_init(&list);
 | 
				
			||||||
		if ((size_t) len < sizeof p)
 | 
						while (len >= 8) {
 | 
				
			||||||
 | 
							size = queue_event(display, len, &list);
 | 
				
			||||||
 | 
							if (size == 0)
 | 
				
			||||||
			break;
 | 
								break;
 | 
				
			||||||
		
 | 
					 | 
				
			||||||
		wl_connection_copy(display->connection, p, sizeof p);
 | 
					 | 
				
			||||||
		object = p[0];
 | 
					 | 
				
			||||||
		opcode = p[1] & 0xffff;
 | 
					 | 
				
			||||||
		size = p[1] >> 16;
 | 
					 | 
				
			||||||
		if (len < size)
 | 
					 | 
				
			||||||
			break;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		handle_event(display, object, opcode, size);
 | 
					 | 
				
			||||||
		len -= size;
 | 
							len -= size;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						while (!wl_list_empty(&list)) {
 | 
				
			||||||
 | 
							closure = container_of(list.next, struct wl_closure, link);
 | 
				
			||||||
 | 
							dispatch_event(display, closure);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return len;
 | 
						return len;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -73,6 +73,7 @@ struct wl_closure {
 | 
				
			||||||
	ffi_cif cif;
 | 
						ffi_cif cif;
 | 
				
			||||||
	void *args[20];
 | 
						void *args[20];
 | 
				
			||||||
	uint32_t *start;
 | 
						uint32_t *start;
 | 
				
			||||||
 | 
						struct wl_list link;
 | 
				
			||||||
	uint32_t buffer[0];
 | 
						uint32_t buffer[0];
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue