static void wl_display_fatal_error(struct wl_display *display, int error) { pthread_mutex_lock(&display->mutex); display_fatal_error(display, error); pthread_mutex_unlock(&display->mutex); }
/** Dispatch events in an event queue * * \param display The display context object * \param queue The event queue to dispatch * \return The number of dispatched events on success or -1 on failure * * 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 wl_display_dispatch_queue(struct wl_display *display, struct wl_event_queue *queue) { struct pollfd pfd[2]; int ret; pthread_mutex_lock(&display->mutex); ret = dispatch_queue(display, queue); if (ret == -1) goto err_unlock; if (ret > 0) { pthread_mutex_unlock(&display->mutex); return ret; } /* We ignore EPIPE here, so that we try to read events before * returning an error. When the compositor sends an error it * will close the socket, and if we bail out here we don't get * a chance to process the error. */ ret = wl_connection_flush(display->connection); if (ret < 0 && errno != EAGAIN && errno != EPIPE) { display_fatal_error(display, errno); goto err_unlock; } display->reader_count++; pthread_mutex_unlock(&display->mutex); pfd[0].fd = display->fd; pfd[0].events = POLLIN; do { ret = poll(pfd, 1, -1); } while (ret == -1 && errno == EINTR); if (ret == -1) { wl_display_cancel_read(display); return -1; } pthread_mutex_lock(&display->mutex); if (read_events(display) == -1) goto err_unlock; ret = dispatch_queue(display, queue); if (ret == -1) goto err_unlock; pthread_mutex_unlock(&display->mutex); return ret; err_unlock: pthread_mutex_unlock(&display->mutex); return -1; }
static int read_events(struct wl_display *display) { int total, rem, size; uint32_t serial; display->reader_count--; if (display->reader_count == 0) { total = wl_connection_read(display->connection); if (total == -1) { if (errno == EAGAIN) return 0; display_fatal_error(display, errno); return -1; } else if (total == 0) { /* The compositor has closed the socket. This * should be considered an error so we'll fake * an errno */ errno = EPIPE; display_fatal_error(display, errno); return -1; } for (rem = total; rem >= 8; rem -= size) { size = queue_event(display, rem); if (size == -1) { display_fatal_error(display, errno); return -1; } else if (size == 0) { break; } } display->read_serial++; pthread_cond_broadcast(&display->reader_cond); } else { serial = display->read_serial; while (display->read_serial == serial) pthread_cond_wait(&display->reader_cond, &display->mutex); } return 0; }
/** Dispatch events in an event queue * * \param display The display context object * \param queue The event queue to dispatch * \return The number of dispatched events on success or -1 on failure * * 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 wl_display_dispatch_queue(struct wl_display *display, struct wl_event_queue *queue) { struct pollfd pfd[2]; int ret; pthread_mutex_lock(&display->mutex); ret = dispatch_queue(display, queue); if (ret == -1) goto err_unlock; if (ret > 0) { pthread_mutex_unlock(&display->mutex); return ret; } ret = wl_connection_flush(display->connection); if (ret < 0 && errno != EAGAIN) { display_fatal_error(display, errno); goto err_unlock; } display->reader_count++; pthread_mutex_unlock(&display->mutex); pfd[0].fd = display->fd; pfd[0].events = POLLIN; do { ret = poll(pfd, 1, -1); } while (ret == -1 && errno == EINTR); if (ret == -1) { wl_display_cancel_read(display); return -1; } pthread_mutex_lock(&display->mutex); if (read_events(display) == -1) goto err_unlock; ret = dispatch_queue(display, queue); if (ret == -1) goto err_unlock; pthread_mutex_unlock(&display->mutex); return ret; err_unlock: pthread_mutex_unlock(&display->mutex); return -1; }
/** Send all buffered requests on the display to the server * * \param display The display context object * \return The number of bytes sent on success or -1 on failure * * Send all buffered data on the client side to the server. Clients * should call this function before blocking. On success, the number * of bytes sent to the server is returned. On failure, this * function returns -1 and errno is set appropriately. * * wl_display_flush() never blocks. It will write as much data as * possible, but if all data could not be written, errno will be set * to EAGAIN and -1 returned. In that case, use poll on the display * file descriptor to wait for it to become writable again. * * \memberof wl_display */ WL_EXPORT int wl_display_flush(struct wl_display *display) { int ret; pthread_mutex_lock(&display->mutex); if (display->last_error) { errno = display->last_error; ret = -1; } else { ret = wl_connection_flush(display->connection); if (ret < 0 && errno != EAGAIN) display_fatal_error(display, errno); } pthread_mutex_unlock(&display->mutex); return ret; }