[PATCH] client: clarify wl_display_prepare_read() semantics
Marek Chalupa
mchqwerty at gmail.com
Mon Aug 4 02:30:46 PDT 2014
>From the doc comment I get the feeling, that after successfull call to
wl_display_prepare_read(), the thread gains exclusive access to the fd.
That is not true. It only ensures that _one_ of the threads, that called
this function, will read from the fd and there will be no race.
Here's slice of the commit message that introduces
wl_display_prepare_read() (3c7e8bfbb4745315b7bcbf69fa746c3d6718c305):
"wl_display_prepare_read() registers the calling thread as a potential
reader of events. Once data is available on the fd, all reader
threads must call wl_display_read_events(), at which point
one of the threads will read from the fd and distribute the events
to event queues. When that is done, all threads return from
wl_display_read_events()."
That is not clear from the doc message.
---
src/wayland-client.c | 27 +++++++++++++++++++++++----
1 file changed, 23 insertions(+), 4 deletions(-)
diff --git a/src/wayland-client.c b/src/wayland-client.c
index 19b5694..d7de24d 100644
--- a/src/wayland-client.c
+++ b/src/wayland-client.c
@@ -1155,6 +1155,12 @@ read_events(struct wl_display *display)
pthread_cond_broadcast(&display->reader_cond);
} else {
serial = display->read_serial;
+ /* in the case that the thread is not allowed to read
+ * from the fd, make it sleep until reading and dispatching
+ * is done. The condition display->read_serial == serial) is
+ * because it may happen, that some thread will call this
+ * function after the reading is done and without this, the
+ * thread would block until next pthread_cond_broadcast */
while (display->read_serial == serial)
pthread_cond_wait(&display->reader_cond,
&display->mutex);
@@ -1180,6 +1186,13 @@ read_events(struct wl_display *display)
* Before calling this function, wl_display_prepare_read() must be
* called first.
*
+ * When more threads call wl_display_prepare_read() to announce the
+ * intention to read from the display's fd, all must call this function
+ * (or wl_display_cancel_read()). Only one thread (at random) will succeed
+ * in reading and the others will block in this function
+ * until the reader is done to avoid races. If this function is called
+ * after the reading is done, it returns immediately.
+ *
* \memberof wl_display
*/
WL_EXPORT int
@@ -1256,15 +1269,21 @@ wl_display_prepare_read_queue(struct wl_display *display,
* This function must be called before reading from the file
* descriptor using wl_display_read_events(). Calling
* wl_display_prepare_read() announces the calling threads intention
- * to read and ensures that until the thread is ready to read and
- * calls wl_display_read_events(), no other thread will read from the
- * file descriptor. This only succeeds if the event queue is empty
+ * to read from the display's fd. This only succeeds if the event queue is empty
* though, and if there are undispatched events in the queue, -1 is
* returned and errno set to EAGAIN.
*
* If a thread successfully calls wl_display_prepare_read(), it must
* either call wl_display_read_events() when it's ready or cancel the
- * read intention by calling wl_display_cancel_read().
+ * read intention by calling wl_display_cancel_read(). After successfull
+ * polling on fd, all threads must call wl_display_read_events() (or cancel).
+ * Only one of them will succeed in reading and once the data are read
+ * and dispatched, all threads return from the function.
+ *
+ * After calling wl_display_prepare_read(), the thread doesn't gain exclusive
+ * access to the fd. It only ensures, that only one thread (at random) will read
+ * from the fd. The non-readers will sleep until the reading is done to avoid races
+ * (see below).
*
* Use this function before polling on the display fd or to integrate
* the fd into a toolkit event loop in a race-free way. Typically, a
--
2.0.4
More information about the wayland-devel
mailing list