예제 #1
0
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);
}
예제 #2
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;
	}

	/* 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;
}
예제 #3
0
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;
}
예제 #4
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;
}
예제 #5
0
/** 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;
}