diff mbox

[02/13] libhinawa: add hinawa context

Message ID 1422185674-16431-3-git-send-email-o-takashi@sakamocchi.jp (mailing list archive)
State New, archived
Headers show

Commit Message

Takashi Sakamoto Jan. 25, 2015, 11:34 a.m. UTC
In this library, 'transaction' consists of a pair of a request and
a response. To achieve the transaction, a requester should wait for
a response from the receiver.

Typically, to achieve the transaction, applications which transfer
requests are blocked with read(2) or poll(2) to wait responses. But
this operation is not good for GUI applications because these
blocking API stops a thread of event loop.

To avoid this situation, this commit adds own 'context'. The context
is running on own thread and execute poll(2). This context can be
written directly with pthreads(7) and select(2)/poll(2)/epoll(7),
but in this time I apply GMainContext/GThread in glib to save my
time.

Signed-off-by: Takashi Sakamoto <o-takashi@sakamocchi.jp>
---
 libhinawa/Makefile.am          |  3 +++
 libhinawa/README               |  1 +
 libhinawa/configure.ac         |  7 +++++
 libhinawa/src/Makefile.am      | 24 +++++++++++++++++
 libhinawa/src/hinawa_context.c | 60 ++++++++++++++++++++++++++++++++++++++++++
 libhinawa/src/hinawa_context.h | 10 +++++++
 6 files changed, 105 insertions(+)
 create mode 100644 libhinawa/src/Makefile.am
 create mode 100644 libhinawa/src/hinawa_context.c
 create mode 100644 libhinawa/src/hinawa_context.h

Comments

Takashi Sakamoto Jan. 27, 2015, 3:35 p.m. UTC | #1
On 2015?01?25? 20:34, Takashi Sakamoto wrote:
> In this library, 'transaction' consists of a pair of a request and
> a response. To achieve the transaction, a requester should wait for
> a response from the receiver.
> 
> Typically, to achieve the transaction, applications which transfer
> requests are blocked with read(2) or poll(2) to wait responses. But
> this operation is not good for GUI applications because these
> blocking API stops a thread of event loop.
> 
> To avoid this situation, this commit adds own 'context'. The context
> is running on own thread and execute poll(2). This context can be
> written directly with pthreads(7) and select(2)/poll(2)/epoll(7),
> but in this time I apply GMainContext/GThread in glib to save my
> time.
> 
> Signed-off-by: Takashi Sakamoto <o-takashi@sakamocchi.jp>

I realize this comment is bad. The strange circuit turned on in my brain
when creating this patch...

This library needs to handle any asynchronous events such as bus-reset
(from FireWire subsystem) or lock/unlock events (from ALSA), thus should
do poll regardless of transactions. In this reason, own thread is required.

> ---
>  libhinawa/Makefile.am          |  3 +++
>  libhinawa/README               |  1 +
>  libhinawa/configure.ac         |  7 +++++
>  libhinawa/src/Makefile.am      | 24 +++++++++++++++++
>  libhinawa/src/hinawa_context.c | 60 ++++++++++++++++++++++++++++++++++++++++++
>  libhinawa/src/hinawa_context.h | 10 +++++++
>  6 files changed, 105 insertions(+)
>  create mode 100644 libhinawa/src/Makefile.am
>  create mode 100644 libhinawa/src/hinawa_context.c
>  create mode 100644 libhinawa/src/hinawa_context.h
> 
> diff --git a/libhinawa/Makefile.am b/libhinawa/Makefile.am
> index e39f07b..05f5d58 100644
> --- a/libhinawa/Makefile.am
> +++ b/libhinawa/Makefile.am
> @@ -1,2 +1,5 @@
>  # Include m4 macros
>  ACLOCAL_AMFLAGS = -I m4 ${ACLOCAL_FLAGS}
> +
> +SUBDIRS =					\
> +	src
> diff --git a/libhinawa/README b/libhinawa/README
> index 234ed91..db9b82a 100644
> --- a/libhinawa/README
> +++ b/libhinawa/README
> @@ -2,6 +2,7 @@ Requirements
>  - GNU Autoconf 2.62 or later
>  - GNU Automake 1.10.1 or later
>  - GNU libtool 2.2.6 or later
> +- Glib 2.32.4 or later
>  
>  How to build
>   $ ./autogen.sh
> diff --git a/libhinawa/configure.ac b/libhinawa/configure.ac
> index 2eeef0d..5ecb7ec 100644
> --- a/libhinawa/configure.ac
> +++ b/libhinawa/configure.ac
> @@ -19,6 +19,9 @@ AC_INIT([hinawa], [my_version], [o-takashi@sakamocchi.jp])
>  AC_CONFIG_AUX_DIR([config])
>  # The directory for M4 macros
>  AC_CONFIG_MACRO_DIR([m4])
> +
> +# The directory for sources
> +AC_CONFIG_SRCDIR([src])
>  # The header for variables with AC_DEFINE
>  AC_CONFIG_HEADERS([config.h])
>  
> @@ -39,9 +42,13 @@ AC_SUBST(LT_IFACE)
>  # Detect C language compiler
>  AC_PROG_CC
>  
> +# Glib 2.32 or later
> +AM_PATH_GLIB_2_0([2.32.4], [], [], [gobject])
> +
>  # The files generated from *.in
>  AC_CONFIG_FILES([
>    Makefile
> +  src/Makefile
>  ])
>  
>  # Generate scripts and launch
> diff --git a/libhinawa/src/Makefile.am b/libhinawa/src/Makefile.am
> new file mode 100644
> index 0000000..5673255
> --- /dev/null
> +++ b/libhinawa/src/Makefile.am
> @@ -0,0 +1,24 @@
> +# Remove auto-generated files when cleaning
> +CLEANFILES =
> +
> +AM_CPPFLAGS =					\
> +	 -I$(top_builddir)			\
> +	 -I$(top_srcdir)
> +
> +AM_CFLAGS =					\
> +	$(GLIB_CFLAGS)				\
> +	-Wall
> +
> +lib_LTLIBRARIES =				\
> +	libhinawa.la
> +
> +libhinawa_la_LDFLAGS =				\
> +	-version-info $(LT_IFACE)
> +
> +libhinawa_la_LIBADD =				\
> +	$(GLIB_LIBS)
> +
> +libhinawa_la_SOURCES =				\
> +	hinawa_context.c
> +
> +pkginclude_HEADERS =
> diff --git a/libhinawa/src/hinawa_context.c b/libhinawa/src/hinawa_context.c
> new file mode 100644
> index 0000000..dd20d21
> --- /dev/null
> +++ b/libhinawa/src/hinawa_context.c
> @@ -0,0 +1,60 @@
> +#include "hinawa_context.h"
> +
> +static GMainContext *ctx;
> +static GThread *thread;
> +
> +static gboolean running;
> +static gint counter;
> +
> +static gpointer run_main_loop(gpointer data)
> +{
> +	while (running)
> +		g_main_context_iteration(ctx, TRUE);
> +
> +	g_thread_exit(NULL);
> +
> +	return NULL;
> +}
> +
> +static GMainContext *get_my_context(GError **exception)
> +{
> +	if (ctx == NULL)
> +		ctx = g_main_context_new();
> +
> +	if (thread == NULL) {
> +		thread = g_thread_try_new("gmain", run_main_loop, NULL,
> +					  exception);
> +		if (*exception != NULL) {
> +			g_main_context_unref(ctx);
> +			ctx = NULL;
> +		}
> +	}
> +
> +	return ctx;
> +}
> +
> +gpointer hinawa_context_add_src(GSource *src, gint fd, GIOCondition event,
> +				GError **exception)
> +{
> +	GMainContext *ctx;
> +
> +	ctx = get_my_context(exception);
> +	if (*exception != NULL)
> +		return NULL;
> +	running = TRUE;
> +
> +	/* NOTE: The returned ID is never used. */
> +	g_source_attach(src, ctx);
> +
> +	return g_source_add_unix_fd(src, fd, event);
> +}
> +
> +void hinawa_context_remove_src(GSource *src)
> +{
> +	g_source_destroy(src);
> +	if (g_atomic_int_dec_and_test(&counter)) {
> +		running = FALSE;
> +		g_thread_join(thread);
> +		thread = NULL;
> +	}
> +}
> diff --git a/libhinawa/src/hinawa_context.h b/libhinawa/src/hinawa_context.h
> new file mode 100644
> index 0000000..97666c6
> --- /dev/null
> +++ b/libhinawa/src/hinawa_context.h
> @@ -0,0 +1,10 @@
> +#ifndef __ALSA_TOOLS_HINAWA_CONTEXT_H__
> +#define __ALSA_TOOLS_HINAWA_CONTEXT_H__
> +
> +#include <glib.h>
> +#include <glib-object.h>
> +
> +gpointer hinawa_context_add_src(GSource *src, gint fd, GIOCondition event,
> +				GError **exception);
> +
> +#endif
>
diff mbox

Patch

diff --git a/libhinawa/Makefile.am b/libhinawa/Makefile.am
index e39f07b..05f5d58 100644
--- a/libhinawa/Makefile.am
+++ b/libhinawa/Makefile.am
@@ -1,2 +1,5 @@ 
 # Include m4 macros
 ACLOCAL_AMFLAGS = -I m4 ${ACLOCAL_FLAGS}
+
+SUBDIRS =					\
+	src
diff --git a/libhinawa/README b/libhinawa/README
index 234ed91..db9b82a 100644
--- a/libhinawa/README
+++ b/libhinawa/README
@@ -2,6 +2,7 @@  Requirements
 - GNU Autoconf 2.62 or later
 - GNU Automake 1.10.1 or later
 - GNU libtool 2.2.6 or later
+- Glib 2.32.4 or later
 
 How to build
  $ ./autogen.sh
diff --git a/libhinawa/configure.ac b/libhinawa/configure.ac
index 2eeef0d..5ecb7ec 100644
--- a/libhinawa/configure.ac
+++ b/libhinawa/configure.ac
@@ -19,6 +19,9 @@  AC_INIT([hinawa], [my_version], [o-takashi@sakamocchi.jp])
 AC_CONFIG_AUX_DIR([config])
 # The directory for M4 macros
 AC_CONFIG_MACRO_DIR([m4])
+
+# The directory for sources
+AC_CONFIG_SRCDIR([src])
 # The header for variables with AC_DEFINE
 AC_CONFIG_HEADERS([config.h])
 
@@ -39,9 +42,13 @@  AC_SUBST(LT_IFACE)
 # Detect C language compiler
 AC_PROG_CC
 
+# Glib 2.32 or later
+AM_PATH_GLIB_2_0([2.32.4], [], [], [gobject])
+
 # The files generated from *.in
 AC_CONFIG_FILES([
   Makefile
+  src/Makefile
 ])
 
 # Generate scripts and launch
diff --git a/libhinawa/src/Makefile.am b/libhinawa/src/Makefile.am
new file mode 100644
index 0000000..5673255
--- /dev/null
+++ b/libhinawa/src/Makefile.am
@@ -0,0 +1,24 @@ 
+# Remove auto-generated files when cleaning
+CLEANFILES =
+
+AM_CPPFLAGS =					\
+	 -I$(top_builddir)			\
+	 -I$(top_srcdir)
+
+AM_CFLAGS =					\
+	$(GLIB_CFLAGS)				\
+	-Wall
+
+lib_LTLIBRARIES =				\
+	libhinawa.la
+
+libhinawa_la_LDFLAGS =				\
+	-version-info $(LT_IFACE)
+
+libhinawa_la_LIBADD =				\
+	$(GLIB_LIBS)
+
+libhinawa_la_SOURCES =				\
+	hinawa_context.c
+
+pkginclude_HEADERS =
diff --git a/libhinawa/src/hinawa_context.c b/libhinawa/src/hinawa_context.c
new file mode 100644
index 0000000..dd20d21
--- /dev/null
+++ b/libhinawa/src/hinawa_context.c
@@ -0,0 +1,60 @@ 
+#include "hinawa_context.h"
+
+static GMainContext *ctx;
+static GThread *thread;
+
+static gboolean running;
+static gint counter;
+
+static gpointer run_main_loop(gpointer data)
+{
+	while (running)
+		g_main_context_iteration(ctx, TRUE);
+
+	g_thread_exit(NULL);
+
+	return NULL;
+}
+
+static GMainContext *get_my_context(GError **exception)
+{
+	if (ctx == NULL)
+		ctx = g_main_context_new();
+
+	if (thread == NULL) {
+		thread = g_thread_try_new("gmain", run_main_loop, NULL,
+					  exception);
+		if (*exception != NULL) {
+			g_main_context_unref(ctx);
+			ctx = NULL;
+		}
+	}
+
+	return ctx;
+}
+
+gpointer hinawa_context_add_src(GSource *src, gint fd, GIOCondition event,
+				GError **exception)
+{
+	GMainContext *ctx;
+
+	ctx = get_my_context(exception);
+	if (*exception != NULL)
+		return NULL;
+	running = TRUE;
+
+	/* NOTE: The returned ID is never used. */
+	g_source_attach(src, ctx);
+
+	return g_source_add_unix_fd(src, fd, event);
+}
+
+void hinawa_context_remove_src(GSource *src)
+{
+	g_source_destroy(src);
+	if (g_atomic_int_dec_and_test(&counter)) {
+		running = FALSE;
+		g_thread_join(thread);
+		thread = NULL;
+	}
+}
diff --git a/libhinawa/src/hinawa_context.h b/libhinawa/src/hinawa_context.h
new file mode 100644
index 0000000..97666c6
--- /dev/null
+++ b/libhinawa/src/hinawa_context.h
@@ -0,0 +1,10 @@ 
+#ifndef __ALSA_TOOLS_HINAWA_CONTEXT_H__
+#define __ALSA_TOOLS_HINAWA_CONTEXT_H__
+
+#include <glib.h>
+#include <glib-object.h>
+
+gpointer hinawa_context_add_src(GSource *src, gint fd, GIOCondition event,
+				GError **exception);
+
+#endif