input handlig in separate thread

Eugen Friedrich friedrix at gmail.com
Sat Oct 19 19:03:06 CEST 2013


Hi Bill,


2013/10/18 Bill Spitzak <spitzak at gmail.com>

> Giulio Camuffo wrote:
>
>> And what is it that doesn't work? As a wild bet I'd say you probably
>> want to look at wl_event_queue.
>> See http://wayland.freedesktop.**org/docs/html/chap-Library.**
>> html#sect-Library-Client<http://wayland.freedesktop.org/docs/html/chap-Library.html#sect-Library-Client>
>>
>
> This brings up some questions I have had about making a complete wayland
> client. The documentation says you should do this:
>
>   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);
>
Now a "real" application or toolkit will need to do a few other
> things:Basicaly
>
* It has to loop
>
> * It has to respond to other fds than the wayland one (yes this could be
> done with threads but I am assuming situations where the overhead and
> difficulty with threads is greater than just handling it in the main
> thread).
>
> * It has to handle timeouts (same comment about threads)
>
> * Most important: it has to have an "idle" (Qt calls it "aboutToBlock")
> handling. FLTK and our Qt programs rely on doing perhaps 90% of their work
> in this, to produce smooth and responsive update with minimal overhead. I
> think *all* toolkits use this as a "now is the time to draw all the
> windows" event.

I will add them here in what I think is the proper places, please inform me
> if this is wrong. The trick is that I have to make sure I don't call poll()
> when any pending events or the queue unlocked, and that any of the
> dispatches can cause more pending events:
>
>   while (!quit) { //ADDED
>     while (wl_display_prepare_read(**display) != 0) {
>       wl_display_dispatch_pending(**display);
>       dispatch_idle(); // ADDED
>     }
>     wl_display_flush(display);
>     poll(...); // with timeout if necessary
>     dispatch_other_fds(); // ADDED
>     dispatch_expired_timeouts(); // ADDED
>     wl_display_read_events(**display);
>     wl_display_dispatch_pending(**display);
>     dispatch_idle(); // ADDED
>   }
>
> The above code assumes that wl_display_dispatch_pending() will consume
> events made pending by it's own dispatches (ie it loops until the queue is
> empty, rather than looping over all events that happen to be in the queue
> when it is called). If this is not true then dispatch_idle() will be called
> more than necessary.
>
> This I believe can be simplified by moving the end of the loop to the
> start to merge identical code, is this correct: ? This reduces the number
> of checks that the queue is empty by at least one:
>
>   bool first = true;
>   while (!quit) {
>     if (first) first = false;
>     else wl_display_read_events(**display);
>     do {
>       wl_display_dispatch_pending(**display);
>       dispatch_idle();
>     } while (wl_display_prepare_read(**display) != 0);
>     wl_display_flush(display);
>     poll(...); // with timeout if necessary
>     dispatch_other_fds();
>     dispatch_expired_timeouts();
>   }
>
> Note: the reason it does the "first" check, rather than putting the
> wl_display_read_events at the end, is because I don't want to call
> wl_display_read_events when quit is true. The earlier version does this
> incorrectly if a timeout or fd turns on quit.
>
> Assuming this is correct, it looks to me like the client has little choice
> about rearranging this and must call in a precise order. So I will propose
> a new function called "wl_i_want_a_pony" so that the main loop looks like
> this:
>
>   while (!quit) {
>     wl_i_want_a_pony(display, dispatch_idle);
>     poll(...);
>     dispatch_other_fds();
>     dispatch_expired_timeouts();
>   }
>
> The implementation of wl_i_want_a_pony is this:
>
>   wl_i_want_a_pony(display, dispatch_idle) {
>     static bool did_prepare_read = false;
>     if (did_prepare_read)
>       wl_display_read_events(**display);
>     do {
>       wl_display_dispatch_pending(**display);
>       dispatch_idle();
>     } while (wl_display_prepare_read(**display) != 0);
>     wl_display_flush(display);
>     did_prepare_read = true;
>   }
>
> Of course in reality the dispatch_idle would be registered with another
> call, and multiple ones allowed. Still this seems like it would reduce the
> size of the wayland client api a lot and remove some of these questions,
> and allow a simpler and more efficient implementation.
>

Basically i would like to implement a thread(input thread) that should
 only dispatch incoming input events from wayland compositor when the
rendering thread is idle and the input thread should sleep in wait for
events function(i think poll on wl_display fd in the example above) without
blocking the rendering thread, because the input events are not the only
one trigger for rendering thread to start rendering again.
in this case the following code should be sufficient right?

while(!quit)//main loop
{
     while (wl_display_prepare_read(**display) != 0)
         wl_display_dispatch_pending(**display);
     wl_display_flush(display);
     poll(fds, nfds, -1); //wait until new input event arrives
     wl_display_read_events(**display);
     wl_display_dispatch_pending(**display);
}

And in this case are there some additional modifications/ wayland calls in
the egl (rendering thread) needed?
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.freedesktop.org/archives/wayland-devel/attachments/20131019/2205997e/attachment.html>


More information about the wayland-devel mailing list