[PATCH] Add support to GCoroutine
- From: Fabiano Fidêncio <fidencio redhat com>
- To: gtk-vnc-list gnome org
- Cc: marcandre lureau gmail com
- Subject: [PATCH] Add support to GCoroutine
- Date: Fri, 9 Jan 2015 01:54:13 +0100
Use GCoroutine, for now optionally, instead of gtk-vnc's own
coroutine implementations.
GCoroutine is library that provides a better coroutine implementation
based on qemu and spice-gtk code and is going to be used for qemu and
spice-gtk as well. The project lives in elmarco's github:
https://github.com/elmarco/gcoroutine
---
configure.ac | 74 ++++++++++++++++++++++++++-------------
src/Makefile.am | 11 ++++--
src/vncconnection.c | 99 ++++++++++++++++++++++++++++++++++++++++++-----------
3 files changed, 137 insertions(+), 47 deletions(-)
diff --git a/configure.ac b/configure.ac
index ecb33cf..150b6c1 100644
--- a/configure.ac
+++ b/configure.ac
@@ -301,41 +301,66 @@ AM_CONDITIONAL([HAVE_SASL], [test "x$with_sasl2" = "xyes" || test "x$with_sasl"
AC_SUBST([SASL_CFLAGS])
AC_SUBST([SASL_LIBS])
+AC_CHECK_LIB(z, inflate, [], [AC_MSG_ERROR([zlib not found])])
+
+AC_ARG_WITH([gcoroutine],
+ [AS_HELP_STRING([--with-gcoroutine=@<:@auto/yes/no@:>@],
+ [use GCoroutine for coroutines instead of the own gtk-vnc implementation
@<:@default=auto@:>@])],
+ [],
+ [with_gcoroutine="auto"])
+
+if test "x$with_gcoroutine" == "xauto" ; then
+ if ${PKG_CONFIG} gcoroutine-1.0 ; then
+ with_gcoroutine=yes;
+ else
+ with_gcoroutine=no;
+ fi
+fi
GTHREAD_CFLAGS=
GTHREAD_LIBS=
-AC_CHECK_LIB(z, inflate, [], [AC_MSG_ERROR([zlib not found])])
-
WITH_UCONTEXT=1
-AC_ARG_WITH(coroutine,
-[ --with-coroutine=ucontext/gthread use ucontext or GThread for coroutines],
-[],[with_coroutine=ucontext])
+if test "x$with_gcoroutine" == "xyes" ; then
+ PKG_CHECK_MODULES(GCOROUTINE, gcoroutine-1.0 >= 0.1.10)
+ AC_SUBST([GCOROUTINE_CFLAGS])
+ AC_SUBST([GCOROUTINE_LIBS])
-case $with_coroutine in
- ucontext)
- ;;
- gthread)
- ;;
- *)
- AC_MSG_ERROR(Unsupported coroutine type)
-esac
+ AC_DEFINE_UNQUOTED([WITH_GCOROUTINE], 1,
+ [Whether GCoroutine is available for coroutines])
-if test "$with_coroutine" = "ucontext"; then
- AC_CHECK_FUNC(makecontext, [],[with_coroutine=gthread])
- AC_CHECK_FUNC(swapcontext, [],[with_coroutine=gthread])
- AC_CHECK_FUNC(getcontext, [],[with_coroutine=gthread])
-fi
+else
+ AC_ARG_WITH(coroutine,
+ [ --with-coroutine=ucontext/gthread use ucontext or GThread for coroutines],
+ [],[with_coroutine=ucontext])
+
+ case $with_coroutine in
+ ucontext)
+ ;;
+ gthread)
+ ;;
+ *)
+ AC_MSG_ERROR(Unsupported coroutine type)
+ esac
+
+ if test "$with_coroutine" = "ucontext"; then
+ AC_CHECK_FUNC(makecontext, [],[with_coroutine=gthread])
+ AC_CHECK_FUNC(swapcontext, [],[with_coroutine=gthread])
+ AC_CHECK_FUNC(getcontext, [],[with_coroutine=gthread])
+ fi
-if test "$with_coroutine" = "gthread"; then
- PKG_CHECK_MODULES(GTHREAD, gthread-2.0 > $GTHREAD_REQUIRED)
- WITH_UCONTEXT=0
+ if test "$with_coroutine" = "gthread"; then
+ PKG_CHECK_MODULES(GTHREAD, gthread-2.0 > $GTHREAD_REQUIRED)
+ WITH_UCONTEXT=0
+ fi
+ AC_SUBST(GTHREAD_CFLAGS)
+ AC_SUBST(GTHREAD_LIBS)
+ AC_DEFINE_UNQUOTED([WITH_UCONTEXT],[$WITH_UCONTEXT], [Whether to use ucontext coroutine impl])
fi
-AC_SUBST(GTHREAD_CFLAGS)
-AC_SUBST(GTHREAD_LIBS)
-AC_DEFINE_UNQUOTED([WITH_UCONTEXT],[$WITH_UCONTEXT], [Whether to use ucontext coroutine impl])
+
AM_CONDITIONAL(WITH_UCONTEXT, [test "$WITH_UCONTEXT" != "0"])
+AM_CONDITIONAL(WITH_GCOROUTINE, [test "x$with_gcoroutine" == "xyes"])
if test "$WITH_PYTHON" = "yes"; then
PKG_CHECK_MODULES(PYGTK, pygtk-2.0 >= $PYGTK_REQUIRED)
@@ -449,4 +474,5 @@ Configure summary:
SASL support................: ${enable_sasl}
PulseAudio support..........: ${HAVE_PULSEAUDIO}
GTK+ version................: ${GTK_API_VERSION}
+ GCoroutine support..........: ${with_gcoroutine}
"
diff --git a/src/Makefile.am b/src/Makefile.am
index f143c90..e6fbc0e 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -34,14 +34,12 @@ endif
libgvnc_1_0_la_LIBADD = \
$(GOBJECT_LIBS) \
$(GIO_LIBS) \
- $(GTHREAD_LIBS) \
$(GDK_PIXBUF_LIBS) \
$(GNUTLS_LIBS) \
$(SASL_LIBS)
libgvnc_1_0_la_CFLAGS = \
$(GOBJECT_CFLAGS) \
$(GIO_CFLAGS) \
- $(GTHREAD_CFLAGS) \
$(GDK_PIXBUF_CFLAGS) \
$(GNUTLS_CFLAGS) \
$(SASL_CFLAGS) \
@@ -120,13 +118,20 @@ libgvncpulse_1_0_la_LDFLAGS = \
-version-info 0:1:0 $(NO_UNDEFINED_FLAGS)
endif
+if WITH_GCOROUTINE
+libgvnc_1_0_la_LIBADD += $(GCOROUTINE_LIBS)
+libgvnc_1_0_la_CFLAGS += $(GCOROUTINE_CFLAGS)
+else
+libgvnc_1_0_la_LIBADD += $(GTHREAD_LIBS)
+libgvnc_1_0_la_CFLAGS += $(GTHREAD_CFLAGS)
if WITH_UCONTEXT
libgvnc_1_0_la_SOURCES += continuation.h continuation.c coroutine_ucontext.c
EXTRA_DIST += coroutine_gthread.c
else
libgvnc_1_0_la_SOURCES += coroutine_gthread.c
EXTRA_DIST += continuation.h continuation.c coroutine_ucontext.c
-endif
+endif #WITH_UCONTEXT
+endif #WITH_GCOROUTINE
gtk_vnc_LIBADD = \
$(GTK_LIBS) \
diff --git a/src/vncconnection.c b/src/vncconnection.c
index ca4d239..cfe8dd5 100644
--- a/src/vncconnection.c
+++ b/src/vncconnection.c
@@ -37,7 +37,12 @@
#include <sys/types.h>
#include <sys/stat.h>
+#ifdef WITH_GCOROUTINE
+#include <gcoroutine.h>
+#else
#include "coroutine.h"
+#endif
+
#include "d3des.h"
#include <gnutls/gnutls.h>
@@ -61,10 +66,22 @@
#define g_mutex_free(m) g_free(m)
#endif
+#ifndef WITH_GCOROUTINE
+
+#define g_coroutine_self() coroutine_self()
+#define g_coroutine_yield(d) coroutine_yield(d)
+#define g_coroutine_resume(c, d) coroutine_yieldto(c, d)
+
+#endif
+
struct wait_queue
{
gboolean waiting;
+#ifdef WITH_GCOROUTINE
+ GCoroutine *context;
+#else
struct coroutine *context;
+#endif
};
typedef enum {
@@ -132,7 +149,11 @@ typedef gboolean (*g_condition_wait_func)(gpointer);
struct g_condition_wait_source
{
GSource src;
+#ifdef WITH_GCOROUTINE
+ GCoroutine *co;
+#else
struct coroutine *co;
+#endif
g_condition_wait_func func;
gpointer data;
};
@@ -143,7 +164,11 @@ struct g_condition_wait_source
struct _VncConnectionPrivate
{
+#ifdef WITH_GCOROUTINE
+ GCoroutine *coroutine;
+#else
struct coroutine coroutine;
+#endif
guint open_id;
GSocket *sock;
GSocketAddress *addr;
@@ -278,8 +303,12 @@ static gboolean g_io_wait_helper(GSocket *sock G_GNUC_UNUSED,
GIOCondition cond,
gpointer data)
{
+#ifdef WITH_GCOROUTINE
+ GCoroutine *to = data;
+#else
struct coroutine *to = data;
- coroutine_yieldto(to, &cond);
+#endif
+ g_coroutine_resume(to, &cond);
return FALSE;
}
@@ -289,9 +318,9 @@ static GIOCondition g_io_wait(GSocket *sock, GIOCondition cond)
GSource *src = g_socket_create_source(sock,
cond | G_IO_HUP | G_IO_ERR | G_IO_NVAL,
NULL);
- g_source_set_callback(src, (GSourceFunc)g_io_wait_helper, coroutine_self(), NULL);
+ g_source_set_callback(src, (GSourceFunc)g_io_wait_helper, g_coroutine_self(), NULL);
g_source_attach(src, NULL);
- ret = coroutine_yield(NULL);
+ ret = g_coroutine_yield(NULL);
g_source_unref(src);
return *ret;
}
@@ -304,7 +333,7 @@ static GIOCondition g_io_wait_interruptable(struct wait_queue *wait,
GIOCondition *ret;
gint id;
- wait->context = coroutine_self();
+ wait->context = g_coroutine_self();
GSource *src = g_socket_create_source(sock,
cond | G_IO_HUP | G_IO_ERR | G_IO_NVAL,
NULL);
@@ -312,7 +341,7 @@ static GIOCondition g_io_wait_interruptable(struct wait_queue *wait,
wait->context, NULL);
id = g_source_attach(src, NULL);
wait->waiting = TRUE;
- ret = coroutine_yield(NULL);
+ ret = g_coroutine_yield(NULL);
g_source_unref(src);
wait->waiting = FALSE;
@@ -326,7 +355,7 @@ static GIOCondition g_io_wait_interruptable(struct wait_queue *wait,
static void g_io_wakeup(struct wait_queue *wait)
{
if (wait->waiting)
- coroutine_yieldto(wait->context, NULL);
+ g_coroutine_resume(wait->context, NULL);
}
@@ -365,8 +394,12 @@ GSourceFuncs waitFuncs = {
static gboolean g_condition_wait_helper(gpointer data)
{
+#ifdef WITH_GCOROUTINE
+ GCoroutine *co = data;
+#else
struct coroutine *co = (struct coroutine *)data;
- coroutine_yieldto(co, NULL);
+#endif
+ g_coroutine_resume(co, NULL);
return FALSE;
}
@@ -389,11 +422,11 @@ static gboolean g_condition_wait(g_condition_wait_func func, gpointer data)
vsrc->func = func;
vsrc->data = data;
- vsrc->co = coroutine_self();
+ vsrc->co = g_coroutine_self();
g_source_attach(src, NULL);
- g_source_set_callback(src, g_condition_wait_helper, coroutine_self(), NULL);
- coroutine_yield(NULL);
+ g_source_set_callback(src, g_condition_wait_helper, g_coroutine_self(), NULL);
+ g_coroutine_yield(NULL);
g_source_unref(src);
return TRUE;
@@ -444,7 +477,11 @@ static void vnc_connection_set_property(GObject *object,
struct signal_data
{
VncConnection *conn;
+#ifdef WITH_GCOROUTINE
+ GCoroutine *caller;
+#else
struct coroutine *caller;
+#endif
int signum;
@@ -584,7 +621,7 @@ static gboolean do_vnc_connection_emit_main_context(gpointer opaque)
g_warn_if_reached();
}
- coroutine_yieldto(data->caller, NULL);
+ g_coroutine_resume(data->caller, NULL);
return FALSE;
}
@@ -594,7 +631,7 @@ static void vnc_connection_emit_main_context(VncConnection *conn,
struct signal_data *data)
{
data->conn = conn;
- data->caller = coroutine_self();
+ data->caller = g_coroutine_self();
data->signum = signum;
g_idle_add(do_vnc_connection_emit_main_context, data);
@@ -605,7 +642,7 @@ static void vnc_connection_emit_main_context(VncConnection *conn,
* from the POV of the VNC coroutine despite there being
* an idle function involved
*/
- coroutine_yield(NULL);
+ g_coroutine_yield(NULL);
}
@@ -2978,7 +3015,11 @@ static gboolean vnc_connection_audio_timer(gpointer opaque)
struct audio_action_data
{
VncConnection *conn;
+#ifdef WITH_GCOROUTINE
+ GCoroutine *caller;
+#else
struct coroutine *caller;
+#endif
enum {
VNC_AUDIO_PLAYBACK_STOP = 0,
VNC_AUDIO_PLAYBACK_START = 1,
@@ -3007,7 +3048,7 @@ static gboolean do_vnc_connection_audio_action(gpointer opaque)
g_warn_if_reached();
}
- coroutine_yieldto(data->caller, NULL);
+ g_coroutine_resume(data->caller, NULL);
return FALSE;
}
@@ -3016,7 +3057,7 @@ static void vnc_connection_audio_action(VncConnection *conn,
{
struct audio_action_data data = {
conn,
- coroutine_self(),
+ g_coroutine_self(),
action,
};
@@ -3030,7 +3071,7 @@ static void vnc_connection_audio_action(VncConnection *conn,
* from the POV of the VNC coroutine despite there being
* an idle function involved
*/
- coroutine_yield(NULL);
+ g_coroutine_yield(NULL);
}
@@ -4545,6 +4586,10 @@ static void vnc_connection_finalize (GObject *object)
g_object_unref(G_OBJECT(priv->audio_sample));
if (priv->audio_timer)
g_source_remove(priv->audio_timer);
+#if WITH_GCOROUTINE
+ if (priv->coroutine)
+ g_coroutine_unref(priv->coroutine);
+#endif
G_OBJECT_CLASS(vnc_connection_parent_class)->finalize (object);
}
@@ -5159,11 +5204,16 @@ static gboolean vnc_connection_open_host_internal(VncConnection *conn)
static gboolean vnc_connection_delayed_unref(gpointer data)
{
VncConnection *conn = VNC_CONNECTION(data);
- VncConnectionPrivate *priv = conn->priv;
-
VNC_DEBUG("Delayed unref VncConnection=%p", conn);
- g_assert(priv->coroutine.exited == TRUE);
+#ifdef WITH_GCOROUTINE
+ g_assert(!g_in_coroutine());
+#else
+ {
+ VncConnectionPrivate *priv = conn->priv;
+ g_assert(priv->coroutine.exited == TRUE);
+ }
+#endif
g_object_unref(G_OBJECT(data));
@@ -5216,11 +5266,18 @@ static gboolean do_vnc_connection_open(gpointer data)
{
VncConnection *conn = VNC_CONNECTION(data);
VncConnectionPrivate *priv = conn->priv;
+#ifdef WITH_GCOROUTINE
+ GCoroutine *co;
+#else
struct coroutine *co;
+#endif
VNC_DEBUG("Open coroutine starting");
priv->open_id = 0;
+#ifdef WITH_GCOROUTINE
+ co = priv->coroutine = g_coroutine_new(vnc_connection_coroutine);
+#else
co = &priv->coroutine;
co->stack_size = 16 << 20;
@@ -5228,7 +5285,9 @@ static gboolean do_vnc_connection_open(gpointer data)
co->release = NULL;
coroutine_init(co);
- coroutine_yieldto(co, conn);
+#endif
+
+ g_coroutine_resume(co, conn);
return FALSE;
}
--
2.1.0
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]