Change filedescriptor API to be thread safe

The update callback for the file descriptors was always a bit awkward and
un-intuitive.  The idea was that whenever the protocol code needed to
write data to the fd it would call the 'update' function.  This function
would adjust the mainloop so that it polls for POLLOUT on the fd so we
can eventually flush the data to the socket.

The problem is that in multi-threaded applications, any thread can issue
a request, which writes data to the output buffer and thus triggers the
update callback.  Thus, we'll be calling out with the display mutex
held and may call from any thread.

The solution is to eliminate the udpate callback and just require that
the application or server flushes all connection buffers before blocking.
This turns out to be a simpler API, although we now require clients to
deal with EAGAIN and non-blocking writes.  It also saves a few syscalls,
since the socket will be writable most of the time and most writes will
complete, so we avoid changing epoll to poll for POLLOUT, then write and
then change it back for each write.
This commit is contained in:
Kristian Høgsberg 2012-10-04 16:54:22 -04:00
parent 0371668dcc
commit 53d24713a3
9 changed files with 150 additions and 251 deletions

View file

@ -54,19 +54,14 @@ void wl_map_for_each(struct wl_map *map, wl_iterator_func_t func, void *data);
struct wl_connection;
struct wl_closure;
#define WL_CONNECTION_READABLE 0x01
#define WL_CONNECTION_WRITABLE 0x02
typedef int (*wl_connection_update_func_t)(struct wl_connection *connection,
uint32_t mask, void *data);
struct wl_connection *wl_connection_create(int fd,
wl_connection_update_func_t update,
void *data);
struct wl_connection *wl_connection_create(int fd);
void wl_connection_destroy(struct wl_connection *connection);
void wl_connection_copy(struct wl_connection *connection, void *data, size_t size);
void wl_connection_consume(struct wl_connection *connection, size_t size);
int wl_connection_data(struct wl_connection *connection, uint32_t mask);
int wl_connection_flush(struct wl_connection *connection);
int wl_connection_read(struct wl_connection *connection);
int wl_connection_write(struct wl_connection *connection, const void *data, size_t count);
int wl_connection_queue(struct wl_connection *connection,
const void *data, size_t count);