Diff between 78d239fd407928fa5b534e1a8d5eba454e52a95d and 87b9e0dc77a84c22cb2fb0d11abf51ef4a2e8f9f

Changed Files

File Additions Deletions Status
src/shared/io-mainloop.c +250 -0 added

Full Patch

diff --git a/src/shared/io-mainloop.c b/src/shared/io-mainloop.c
new file mode 100644
index 0000000..981ab17
--- /dev/null
+++ b/src/shared/io-mainloop.c
@@ -0,0 +1,250 @@
+/*
+ *
+ *  BlueZ - Bluetooth protocol stack for Linux
+ *
+ *  Copyright (C) 2012  Intel Corporation. All rights reserved.
+ *
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2.1 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <unistd.h>
+
+#include "monitor/mainloop.h"
+#include "src/shared/util.h"
+#include "src/shared/io.h"
+
+struct io {
+	int ref_count;
+	int fd;
+	uint32_t events;
+	bool close_on_destroy;
+	io_callback_func_t read_callback;
+	io_destroy_func_t read_destroy;
+	void *read_data;
+	io_callback_func_t write_callback;
+	io_destroy_func_t write_destroy;
+	void *write_data;
+};
+
+static struct io *io_ref(struct io *io)
+{
+	if (!io)
+		return NULL;
+
+	__sync_fetch_and_add(&io->ref_count, 1);
+
+	return io;
+}
+
+static void io_unref(struct io *io)
+{
+	if (!io)
+		return;
+
+	if (__sync_sub_and_fetch(&io->ref_count, 1))
+		return;
+
+	free(io);
+}
+
+static void io_cleanup(void *user_data)
+{
+	struct io *io = user_data;
+
+	if (io->write_destroy)
+		io->write_destroy(io->write_data);
+
+	if (io->read_destroy)
+		io->read_destroy(io->read_data);
+
+	if (io->close_on_destroy)
+		close(io->fd);
+
+	io->fd = -1;
+}
+
+static void io_callback(int fd, uint32_t events, void *user_data)
+{
+	struct io *io = user_data;
+
+	if (events & (EPOLLERR | EPOLLHUP)) {
+		io->read_callback = NULL;
+		io->write_callback = NULL;
+
+		mainloop_remove_fd(io->fd);
+		return;
+	}
+
+	if ((events & EPOLLIN) && io->read_callback) {
+		if (!io->read_callback(io, io->read_data)) {
+			if (io->read_destroy)
+				io->read_destroy(io->read_data);
+
+			io->read_callback = NULL;
+			io->read_destroy = NULL;
+			io->read_data = NULL;
+
+			io->events &= ~EPOLLIN;
+
+			mainloop_modify_fd(io->fd, io->events);
+		}
+	}
+
+	if ((events & EPOLLOUT) && io->write_callback) {
+		if (!io->write_callback(io, io->write_data)) {
+			if (io->write_destroy)
+				io->write_destroy(io->write_data);
+
+			io->write_callback = NULL;
+			io->write_destroy = NULL;
+			io->write_data = NULL;
+
+			io->events &= ~EPOLLOUT;
+
+			mainloop_modify_fd(io->fd, io->events);
+		}
+	}
+}
+
+struct io *io_new(int fd)
+{
+	struct io *io;
+
+	if (fd < 0)
+		return NULL;
+
+	io = new0(struct io, 1);
+	if (!io)
+		return NULL;
+
+	io->fd = fd;
+	io->events = 0;
+	io->close_on_destroy = false;
+
+	if (mainloop_add_fd(io->fd, io->events, io_callback,
+						io, io_cleanup) < 0) {
+		free(io);
+		return NULL;
+	}
+
+	return io_ref(io);
+}
+
+void io_destroy(struct io *io)
+{
+	if (!io)
+		return;
+
+	mainloop_remove_fd(io->fd);
+
+	io->read_callback = NULL;
+	io->write_callback = NULL;
+
+	mainloop_remove_fd(io->fd);
+
+	io_unref(io);
+}
+
+int io_get_fd(struct io *io)
+{
+	if (!io)
+		return -1;
+
+	return io->fd;
+}
+
+bool io_set_close_on_destroy(struct io *io, bool do_close)
+{
+	if (!io)
+		return false;
+
+	io->close_on_destroy = do_close;
+
+	return true;
+}
+
+bool io_set_read_handler(struct io *io, io_callback_func_t callback,
+				void *user_data, io_destroy_func_t destroy)
+{
+	uint32_t events;
+
+	if (!io || io->fd < 0)
+		return false;
+
+	if (io->read_destroy)
+		io->read_destroy(io->read_data);
+
+	if (callback)
+		events = io->events | EPOLLIN;
+	else
+		events = io->events & ~EPOLLIN;
+
+	io->read_callback = callback;
+	io->read_destroy = destroy;
+	io->read_data = user_data;
+
+	if (events == io->events)
+		return true;
+
+	if (mainloop_modify_fd(io->fd, events) < 0)
+		return false;
+
+	io->events = events;
+
+	return true;
+}
+
+bool io_set_write_handler(struct io *io, io_callback_func_t callback,
+				void *user_data, io_destroy_func_t destroy)
+{
+	uint32_t events;
+
+	if (!io || io->fd < 0)
+		return false;
+
+	if (io->write_destroy)
+		io->write_destroy(io->write_data);
+
+	if (callback)
+		events = io->events | EPOLLOUT;
+	else
+		events = io->events & ~EPOLLOUT;
+
+	io->write_callback = callback;
+	io->write_destroy = destroy;
+	io->write_data = user_data;
+
+	if (events == io->events)
+		return true;
+
+	if (mainloop_modify_fd(io->fd, events) < 0)
+		return false;
+
+	io->events = events;
+
+	return true;
+}
+
+bool io_set_disconnect_handler(struct io *io, io_callback_func_t callback,
+				void *user_data, io_destroy_func_t destroy)
+{
+	return false;
+}