[PATCH] client: Add wl_display_prepare_read() API to thread model assumptions

Bill Spitzak spitzak at gmail.com
Wed May 1 11:46:51 PDT 2013


Kristian Høgsberg wrote:

> + * A correct sequence would be:
> + *
> + *   while (wl_display_prepare_read(display) != 0)
> + *           wl_display_dispatch_pending(display);
> + *   wl_display_flush(display);
> + *   poll(fds, nfds, -1);
> + *   wl_display_read_events(display);
> + *   wl_display_dispatch_pending(display);

When writing a client I need to do "idle" effects (what Qt calls 
"aboutToBlock"), in particular redrawing all damaged surfaces. This may 
trigger more events so it has to be in the prepare loop. I need to 
remove the second dispatch, because I need to make sure draw is called 
if any events are handled but I don't want to call it an extra time if 
prepare indicates more events. This also I think removes a redundant 
test for pending events that is repeated by the prepare_read():

   mainloop() {
     for (;;) {
       while (wl_display_prepare_read(display) != 0) {
         wl_display_dispatch_pending(display);
         draw_damaged_surfaces();
       }
       wl_display_flush(display);
       poll(fds, nfds, -1);
       wl_display_read_events(display);
     }
   }

Now I'm wondering if dispatch_pending is *ever* called without the 
prepare_read(). Perhaps these can be replaced with a single function 
that is the equivalent of:

   wl_foo(display) {
      if (wl_display_prepare_read(display)) {
        wl_display_dispatch_pending(display);
        return true;
      } else {
        return false;
      }
   }

And the main loop looks like this:

   mainloop() {
     for (;;) {
       while (wl_foo(display))
         draw_damaged_surfaces();
       wl_display_flush(display);
       poll(fds, nfds, -1);
       wl_display_read_events(display);
     }
   }

If clients have to register the idle callback then this function could 
do the loop as well, which may be more efficient and allows error 
indicators to be returned. I think it could even do a blocking 
read_events() and the display_flush(). Then the main loop looks like this:

   mainloop() {
     wl_add_idle_callback(draw_damaged_surfaces);
     for (;;) {
       poll(fds, nfds, -1);
       if (wl_foo()) abort();
     }
   }



More information about the wayland-devel mailing list