[PATCH wayland 1/2] doc: Clarify documentation about dispatching event queues

Kristian Høgsberg hoegsberg at gmail.com
Fri Oct 19 13:50:59 PDT 2012


On Fri, Oct 19, 2012 at 03:30:25PM +0300, Ander Conselvan de Oliveira wrote:
> Clarify on what cases each of the dispatching functions may block, what
> is the main thread and add some real world examples.
> ---
> 
> Hi Kristian,
> 
> Hopefully I got it right this time. The documentation for
> wl_display_dispatch_pending() is pretty much a reword of your answer
> to my previous patch.
> 
> Feel free to amend any changes you see necessary.

No, this looks good, thanks.

Kristian

> Thanks,
> Ander
> 
>  src/wayland-client.c |   58 ++++++++++++++++++++++++++++++++++++++++++++++++--
>  src/wayland-client.h |   52 +++++++++++++++++++++++++++++++++-----------
>  2 files changed, 96 insertions(+), 14 deletions(-)
> 
> diff --git a/src/wayland-client.c b/src/wayland-client.c
> index ccf8174..7e50b40 100644
> --- a/src/wayland-client.c
> +++ b/src/wayland-client.c
> @@ -824,6 +824,11 @@ err_unlock:
>   * Dispatch all incoming events for objects assigned to the given
>   * event queue. On failure -1 is returned and errno set appropriately.
>   *
> + * This function blocks if there are no events to dispatch. If calling from
> + * the main thread, it will block reading data from the display fd. For other
> + * threads this will block until the main thread queues events on the queue
> + * passed as argument.
> + *
>   * \memberof wl_display
>   */
>  WL_EXPORT int
> @@ -833,14 +838,25 @@ wl_display_dispatch_queue(struct wl_display *display,
>  	return dispatch_queue(display, queue, 1);
>  }
>  
> -/** Dispatch a display's main event queue
> +/** Process incoming events
>   *
>   * \param display The display context object
>   * \return The number of dispatched events on success or -1 on failure
>   *
>   * Dispatch the display's main event queue.
>   *
> - * \sa wl_display_dispatch_queue()
> + * If the main event queue is empty, this function blocks until there are
> + * events to be read from the display fd. Events are read and queued on
> + * the appropriate event queues. Finally, events on the main event queue
> + * are dispatched.
> + *
> + * \note It is not possible to check if there are events on the main queue
> + * or not. For dispatching main queue events without blocking, see \ref
> + * wl_display_dispatch_pending().
> + *
> + * \note Calling this makes the current thread the main one.
> + *
> + * \sa wl_display_dispatch_pending(), wl_display_dispatch_queue()
>   *
>   * \memberof wl_display
>   */
> @@ -852,6 +868,44 @@ wl_display_dispatch(struct wl_display *display)
>  	return dispatch_queue(display, &display->queue, 1);
>  }
>  
> +/** Dispatch main queue events without reading from the display fd
> + *
> + * \param display The display context object
> + * \return The number of dispatched events or -1 on failure
> + *
> + * This function dispatches events on the main event queue. It does not
> + * attempt to read the display fd and simply returns zero if the main
> + * queue is empty, i.e., it doesn't block.
> + *
> + * This is necessary when a client's main loop wakes up on some fd other
> + * than the display fd (network socket, timer fd, etc) and calls \ref
> + * wl_display_dispatch_queue() from that callback. This may queue up
> + * events in the main queue while reading all data from the display fd.
> + * When the main thread returns to the main loop to block, the display fd
> + * no longer has data, causing a call to \em poll(2) (or similar
> + * functions) to block indefinitely, even though there are events ready
> + * to dispatch.
> + *
> + * To proper integrate the wayland display fd into a main loop, the
> + * client should always call \ref wl_display_dispatch_pending() and then
> + * \ref wl_display_flush() prior to going back to sleep. At that point,
> + * the fd typically doesn't have data so attempting I/O could block, but
> + * events queued up on the main queue should be dispatched.
> + *
> + * A real-world example is a main loop that wakes up on a timerfd (or a
> + * sound card fd becoming writable, for example in a video player), which
> + * then triggers GL rendering and eventually eglSwapBuffers().
> + * eglSwapBuffers() may call wl_display_dispatch_queue() if it didn't
> + * receive the frame event for the previous frame, and as such queue
> + * events in the main queue.
> + *
> + * \note Calling this makes the current thread the main one.
> + *
> + * \sa wl_display_dispatch(), wl_display_dispatch_queue(),
> + * wl_display_flush()
> + *
> + * \memberof wl_display
> + */
>  WL_EXPORT int
>  wl_display_dispatch_pending(struct wl_display *display)
>  {
> diff --git a/src/wayland-client.h b/src/wayland-client.h
> index fb9c952..71fe450 100644
> --- a/src/wayland-client.h
> +++ b/src/wayland-client.h
> @@ -66,18 +66,46 @@ struct wl_proxy;
>   * representation to the display's write buffer. The data is sent to the
>   * compositor when the client calls \ref wl_display_flush().
>   *
> - * Event handling is done in a thread-safe manner using event queues. The
> - * display has a \em main event queue where initially all the events are
> - * queued. The listeners for the events queued in it are called when the
> - * client calls \ref wl_display_dispatch().
> - *
> - * The client can create additional event queues with \ref
> - * wl_display_create_queue() and assign different \ref wl_proxy objects to it.
> - * The events for a proxy are always queued only on its assign queue, that can
> - * be dispatched by a different thread with \ref wl_display_dispatch_queue().
> - *
> - * All the \ref wl_display's functions are thread-safe.
> - *
> + * Incoming data is handled in two steps: queueing and dispatching. In the
> + * queue step, the data coming from the display fd is interpreted and
> + * added to a queue. On the dispatch step, the handler for the incoming
> + * event set by the client on the corresponding \ref wl_proxy is called.
> + *
> + * A \ref wl_display has at least one event queue, called the <em>main
> + * queue</em>. Clients can create additional event queues with \ref
> + * wl_display_create_queue() and assign \ref wl_proxy's to it. Events
> + * occurring in a particular proxy are always queued in its assigned queue.
> + * A client can ensure that a certain assumption, such as holding a lock
> + * or running from a given thread, is true when a proxy event handler is
> + * called by assigning that proxy to an event queue and making sure that
> + * this queue is only dispatched when the assumption holds.
> + *
> + * The main queue is dispatched by calling \ref wl_display_dispatch().
> + * This will dispatch any events queued on the main queue and attempt
> + * to read from the display fd if its empty. Events read are then queued
> + * on the appropriate queues according to the proxy assignment. Calling
> + * that function makes the calling thread the <em>main thread</em>.
> + *
> + * A user created queue is dispatched with \ref wl_display_dispatch_queue().
> + * If there are no events to dispatch this function will block. If this
> + * is called by the main thread, this will attempt to read data from the
> + * display fd and queue any events on the appropriate queues. If calling
> + * from any other thread, the function will block until the main thread
> + * queues an event on the queue being dispatched.
> + *
> + * A real world example of event queue usage is Mesa's implementation of
> + * eglSwapBuffers() for the Wayland platform. This function might need
> + * to block until a frame callback is received, but dispatching the main
> + * queue could cause an event handler on the client to start drawing
> + * again. This problem is solved using another event queue, so that only
> + * the events handled by the EGL code are dispatched during the block.
> + *
> + * This creates a problem where the main thread dispatches a non-main
> + * queue, reading all the data from the display fd. If the application
> + * would call \em poll(2) after that it would block, even though there
> + * might be events queued on the main queue. Those events should be
> + * dispatched with \ref wl_display_dispatch_pending() before
> + * flushing and blocking.
>   */
>  struct wl_display;
>  
> -- 
> 1.7.9.5
> 
> _______________________________________________
> 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