From 8e3982dd422671d26a653f393639cd12cd01ff18 Mon Sep 17 00:00:00 2001
From: Max Kellermann <max@duempel.org>
Date: Mon, 14 Jan 2013 09:52:35 +0100
Subject: InotifySource: convert to a class

---
 src/InotifySource.cxx | 100 ++++++++++++++++++++------------------------------
 src/InotifySource.hxx |  76 ++++++++++++++++++++++++--------------
 src/InotifyUpdate.cxx |  18 ++++-----
 test/run_inotify.cxx  |  12 +++---
 4 files changed, 101 insertions(+), 105 deletions(-)

diff --git a/src/InotifySource.cxx b/src/InotifySource.cxx
index 16fd62511..f795733d8 100644
--- a/src/InotifySource.cxx
+++ b/src/InotifySource.cxx
@@ -36,22 +36,6 @@ extern "C" {
 #undef G_LOG_DOMAIN
 #define G_LOG_DOMAIN "inotify"
 
-struct mpd_inotify_source {
-	int fd;
-
-	GIOChannel *channel;
-
-	/**
-	 * The channel's source id in the GLib main loop.
-	 */
-	guint id;
-
-	struct fifo_buffer *buffer;
-
-	mpd_inotify_callback_t callback;
-	void *callback_ctx;
-};
-
 /**
  * A GQuark for GError instances.
  */
@@ -61,35 +45,32 @@ mpd_inotify_quark(void)
 	return g_quark_from_static_string("inotify");
 }
 
-static gboolean
-mpd_inotify_in_event(G_GNUC_UNUSED GIOChannel *_source,
-		     G_GNUC_UNUSED GIOCondition condition,
-		     gpointer data)
+inline void
+InotifySource::InEvent()
 {
-	struct mpd_inotify_source *source = (struct mpd_inotify_source *)data;
 	void *dest;
 	size_t length;
 	ssize_t nbytes;
 
-	dest = fifo_buffer_write(source->buffer, &length);
+	dest = fifo_buffer_write(buffer, &length);
 	if (dest == NULL)
 		MPD_ERROR("buffer full");
 
-	nbytes = read(source->fd, dest, length);
+	nbytes = read(fd, dest, length);
 	if (nbytes < 0)
 		MPD_ERROR("failed to read from inotify: %s",
 			  g_strerror(errno));
 	if (nbytes == 0)
 		MPD_ERROR("end of file from inotify");
 
-	fifo_buffer_append(source->buffer, nbytes);
+	fifo_buffer_append(buffer, nbytes);
 
 	while (true) {
 		const char *name;
 
 		const struct inotify_event *event =
 			(const struct inotify_event *)
-			fifo_buffer_read(source->buffer, &length);
+			fifo_buffer_read(buffer, &length);
 		if (event == NULL || length < sizeof(*event) ||
 		    length < sizeof(*event) + event->len)
 			break;
@@ -99,59 +80,58 @@ mpd_inotify_in_event(G_GNUC_UNUSED GIOChannel *_source,
 		else
 			name = NULL;
 
-		source->callback(event->wd, event->mask, name,
-				 source->callback_ctx);
-		fifo_buffer_consume(source->buffer,
-				    sizeof(*event) + event->len);
+		callback(event->wd, event->mask, name, callback_ctx);
+		fifo_buffer_consume(buffer, sizeof(*event) + event->len);
 	}
+}
 
+gboolean
+InotifySource::InEvent(G_GNUC_UNUSED GIOChannel *_source,
+		       G_GNUC_UNUSED GIOCondition condition,
+		       gpointer data)
+{
+	InotifySource &source = *(InotifySource *)data;
+	source.InEvent();
 	return true;
 }
 
-struct mpd_inotify_source *
-mpd_inotify_source_new(mpd_inotify_callback_t callback, void *callback_ctx,
-		       GError **error_r)
+inline
+InotifySource::InotifySource(mpd_inotify_callback_t _callback, void *_ctx,
+			     int _fd)
+	:callback(_callback), callback_ctx(_ctx), fd(_fd),
+	 channel(g_io_channel_unix_new(fd)),
+	 id(g_io_add_watch(channel, G_IO_IN, InEvent, this)),
+	 buffer(fifo_buffer_new(4096))
 {
-	struct mpd_inotify_source *source =
-		g_new(struct mpd_inotify_source, 1);
+}
 
-	source->fd = inotify_init_cloexec();
-	if (source->fd < 0) {
+InotifySource *
+InotifySource::Create(mpd_inotify_callback_t callback, void *callback_ctx,
+		      GError **error_r)
+{
+	int fd = inotify_init_cloexec();
+	if (fd < 0) {
 		g_set_error(error_r, mpd_inotify_quark(), errno,
 			    "inotify_init() has failed: %s",
 			    g_strerror(errno));
-		g_free(source);
 		return NULL;
 	}
 
-	source->buffer = fifo_buffer_new(4096);
-
-	source->channel = g_io_channel_unix_new(source->fd);
-	source->id = g_io_add_watch(source->channel, G_IO_IN,
-				    mpd_inotify_in_event, source);
-
-	source->callback = callback;
-	source->callback_ctx = callback_ctx;
-
-	return source;
+	return new InotifySource(callback, callback_ctx, fd);
 }
 
-void
-mpd_inotify_source_free(struct mpd_inotify_source *source)
+InotifySource::~InotifySource()
 {
-	g_source_remove(source->id);
-	g_io_channel_unref(source->channel);
-	fifo_buffer_free(source->buffer);
-	close(source->fd);
-	g_free(source);
+	g_source_remove(id);
+	g_io_channel_unref(channel);
+	fifo_buffer_free(buffer);
+	close(fd);
 }
 
 int
-mpd_inotify_source_add(struct mpd_inotify_source *source,
-		       const char *path_fs, unsigned mask,
-		       GError **error_r)
+InotifySource::Add(const char *path_fs, unsigned mask, GError **error_r)
 {
-	int wd = inotify_add_watch(source->fd, path_fs, mask);
+	int wd = inotify_add_watch(fd, path_fs, mask);
 	if (wd < 0)
 		g_set_error(error_r, mpd_inotify_quark(), errno,
 			    "inotify_add_watch() has failed: %s",
@@ -161,9 +141,9 @@ mpd_inotify_source_add(struct mpd_inotify_source *source,
 }
 
 void
-mpd_inotify_source_rm(struct mpd_inotify_source *source, unsigned wd)
+InotifySource::Remove(unsigned wd)
 {
-	int ret = inotify_rm_watch(source->fd, wd);
+	int ret = inotify_rm_watch(fd, wd);
 	if (ret < 0 && errno != EINVAL)
 		g_warning("inotify_rm_watch() has failed: %s",
 			  g_strerror(errno));
diff --git a/src/InotifySource.hxx b/src/InotifySource.hxx
index cde2bc269..6299d1e20 100644
--- a/src/InotifySource.hxx
+++ b/src/InotifySource.hxx
@@ -22,40 +22,60 @@
 
 #include "gerror.h"
 
+#include <glib.h>
+
 typedef void (*mpd_inotify_callback_t)(int wd, unsigned mask,
 				       const char *name, void *ctx);
 
-struct mpd_inotify_source;
+class InotifySource {
+	mpd_inotify_callback_t callback;
+	void *callback_ctx;
 
-/**
- * Creates a new inotify source and registers it in the GLib main
- * loop.
- *
- * @param a callback invoked for events received from the kernel
- */
-struct mpd_inotify_source *
-mpd_inotify_source_new(mpd_inotify_callback_t callback, void *callback_ctx,
-		       GError **error_r);
+	int fd;
 
-void
-mpd_inotify_source_free(struct mpd_inotify_source *source);
+	GIOChannel *channel;
 
-/**
- * Adds a path to the notify list.
- *
- * @return a watch descriptor or -1 on error
- */
-int
-mpd_inotify_source_add(struct mpd_inotify_source *source,
-		       const char *path_fs, unsigned mask,
-		       GError **error_r);
+	/**
+	 * The channel's source id in the GLib main loop.
+	 */
+	guint id;
 
-/**
- * Removes a path from the notify list.
- *
- * @param wd the watch descriptor returned by mpd_inotify_source_add()
- */
-void
-mpd_inotify_source_rm(struct mpd_inotify_source *source, unsigned wd);
+	struct fifo_buffer *buffer;
+
+	InotifySource(mpd_inotify_callback_t callback, void *ctx, int fd);
+
+public:
+	/**
+	 * Creates a new inotify source and registers it in the GLib main
+	 * loop.
+	 *
+	 * @param a callback invoked for events received from the kernel
+	 */
+	static InotifySource *Create(mpd_inotify_callback_t callback,
+				     void *ctx,
+				     GError **error_r);
+
+	~InotifySource();
+
+
+	/**
+	 * Adds a path to the notify list.
+	 *
+	 * @return a watch descriptor or -1 on error
+	 */
+	int Add(const char *path_fs, unsigned mask, GError **error_r);
+
+	/**
+	 * Removes a path from the notify list.
+	 *
+	 * @param wd the watch descriptor returned by mpd_inotify_source_add()
+	 */
+	void Remove(unsigned wd);
+
+private:
+	void InEvent();
+	static gboolean InEvent(GIOChannel *source, GIOCondition condition,
+				gpointer data);
+};
 
 #endif
diff --git a/src/InotifyUpdate.cxx b/src/InotifyUpdate.cxx
index b7bb3af2b..41b93a299 100644
--- a/src/InotifyUpdate.cxx
+++ b/src/InotifyUpdate.cxx
@@ -56,7 +56,7 @@ struct watch_directory {
 	GList *children;
 };
 
-static struct mpd_inotify_source *inotify_source;
+static InotifySource *inotify_source;
 
 static unsigned inotify_max_depth;
 static struct watch_directory inotify_root;
@@ -117,7 +117,7 @@ remove_watch_directory(struct watch_directory *directory)
 	directory->parent->children =
 		g_list_remove(directory->parent->children, directory);
 
-	mpd_inotify_source_rm(inotify_source, directory->descriptor);
+	inotify_source->Remove(directory->descriptor);
 	g_free(directory->name);
 	g_slice_free(struct watch_directory, directory);
 }
@@ -195,8 +195,7 @@ recursive_watch_subdirectories(struct watch_directory *directory,
 			continue;
 		}
 
-		ret = mpd_inotify_source_add(inotify_source, child_path_fs,
-					     IN_MASK, &error);
+		ret = inotify_source->Add(child_path_fs, IN_MASK, &error);
 		if (ret < 0) {
 			g_warning("Failed to register %s: %s",
 				  child_path_fs, error->message);
@@ -317,8 +316,8 @@ mpd_inotify_init(unsigned max_depth)
 		return;
 	}
 
-	inotify_source = mpd_inotify_source_new(mpd_inotify_callback, NULL,
-						&error);
+	inotify_source = InotifySource::Create(mpd_inotify_callback, nullptr,
+					       &error);
 	if (inotify_source == NULL) {
 		g_warning("%s", error->message);
 		g_error_free(error);
@@ -328,12 +327,11 @@ mpd_inotify_init(unsigned max_depth)
 	inotify_max_depth = max_depth;
 
 	inotify_root.name = g_strdup(path);
-	inotify_root.descriptor = mpd_inotify_source_add(inotify_source, path,
-							 IN_MASK, &error);
+	inotify_root.descriptor = inotify_source->Add(path, IN_MASK, &error);
 	if (inotify_root.descriptor < 0) {
 		g_warning("%s", error->message);
 		g_error_free(error);
-		mpd_inotify_source_free(inotify_source);
+		delete inotify_source;
 		inotify_source = NULL;
 		return;
 	}
@@ -370,7 +368,7 @@ mpd_inotify_finish(void)
 		return;
 
 	mpd_inotify_queue_finish();
-	mpd_inotify_source_free(inotify_source);
+	delete inotify_source;
 
 	g_tree_foreach(inotify_directories, free_watch_directory, NULL);
 	g_tree_destroy(inotify_directories);
diff --git a/test/run_inotify.cxx b/test/run_inotify.cxx
index 7052210b1..92790a3a3 100644
--- a/test/run_inotify.cxx
+++ b/test/run_inotify.cxx
@@ -61,19 +61,17 @@ int main(int argc, char **argv)
 
 	path = argv[1];
 
-	struct mpd_inotify_source *source =
-		mpd_inotify_source_new(my_inotify_callback, NULL,
-				       &error);
+	InotifySource *source = InotifySource::Create(my_inotify_callback,
+						      nullptr, &error);
 	if (source == NULL) {
 		g_warning("%s", error->message);
 		g_error_free(error);
 		return 2;
 	}
 
-	int descriptor = mpd_inotify_source_add(source, path,
-						IN_MASK, &error);
+	int descriptor = source->Add(path, IN_MASK, &error);
 	if (descriptor < 0) {
-		mpd_inotify_source_free(source);
+		delete source;
 		g_warning("%s", error->message);
 		g_error_free(error);
 		return 2;
@@ -90,6 +88,6 @@ int main(int argc, char **argv)
 
 	event_loop->Run();
 
-	mpd_inotify_source_free(source);
+	delete source;
 	delete event_loop;
 }
-- 
cgit v1.2.3