static void marshal_demarshal(struct marshal_data *data, void (*func)(void), int size, const char *format, ...) { struct wl_closure *closure; static const int opcode = 4444; static struct wl_object sender = { NULL, NULL, 1234 }; struct wl_message message = { "test", format, NULL }; struct wl_map objects; struct wl_object object = { NULL, &func, 0 }; va_list ap; uint32_t msg[1] = { 1234 }; va_start(ap, format); closure = wl_closure_vmarshal(&sender, opcode, ap, &message); va_end(ap); assert(closure); assert(wl_closure_send(closure, data->write_connection) == 0); wl_closure_destroy(closure); assert(wl_connection_flush(data->write_connection) == size); assert(wl_connection_read(data->read_connection) == size); wl_map_init(&objects, WL_MAP_SERVER_SIDE); object.id = msg[0]; closure = wl_connection_demarshal(data->read_connection, size, &objects, &message); assert(closure); wl_closure_invoke(closure, WL_CLOSURE_INVOKE_SERVER, &object, 0, data); wl_closure_destroy(closure); }
/** 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; }
/** 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; }
static int wl_connection_put_fd(struct wl_connection *connection, int32_t fd) { if (wl_buffer_size(&connection->fds_out) == MAX_FDS_OUT * sizeof fd) { connection->want_flush = 1; if (wl_connection_flush(connection) < 0) return -1; } return wl_buffer_put(&connection->fds_out, &fd, sizeof fd); }
int wl_connection_queue(struct wl_connection *connection, const void *data, size_t count) { if (connection->out.head - connection->out.tail + count > ARRAY_LENGTH(connection->out.data)) { connection->want_flush = 1; if (wl_connection_flush(connection) < 0) return -1; } return wl_buffer_put(&connection->out, data, count); }
/** 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; }
static void marshal(struct marshal_data *data, const char *format, int size, ...) { struct wl_closure *closure; static const uint32_t opcode = 4444; static struct wl_object sender = { NULL, NULL, 1234 }; struct wl_message message = { "test", format, NULL }; va_list ap; va_start(ap, size); closure = wl_closure_vmarshal(&sender, opcode, ap, &message); va_end(ap); assert(closure); assert(wl_closure_send(closure, data->write_connection) == 0); wl_closure_destroy(closure); assert(wl_connection_flush(data->write_connection) == size); assert(read(data->s[0], data->buffer, sizeof data->buffer) == size); assert(data->buffer[0] == sender.id); assert(data->buffer[1] == (opcode | (size << 16))); }