[libgda] Allow gda_connection_set_main_context() to work with multiple contexts
- From: Vivien Malerba <vivien src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [libgda] Allow gda_connection_set_main_context() to work with multiple contexts
- Date: Wed, 2 Apr 2014 19:33:45 +0000 (UTC)
commit 54746d5124dc6c460f96eae3268f653b7b4218dc
Author: Vivien Malerba <malerba gnome-db org>
Date: Wed Apr 2 18:33:08 2014 +0200
Allow gda_connection_set_main_context() to work with multiple contexts
libgda-ui/demos/main.c | 2 +-
libgda/gda-connection-private.h | 1 +
libgda/gda-connection.c | 181 ++++++++++++++++++++---------------
libgda/gda-connection.h | 8 +-
libgda/gda-server-provider.c | 6 +-
libgda/test-cnc-exec.c | 111 +++++++++++++++++++++-
libgda/test-cnc-meta.c | 2 +-
libgda/test-cnc-open.c | 71 ++++++++++++++-
libgda/thread-wrapper/gda-worker.c | 17 ++++
libgda/thread-wrapper/gda-worker.h | 1 +
10 files changed, 309 insertions(+), 91 deletions(-)
---
diff --git a/libgda-ui/demos/main.c b/libgda-ui/demos/main.c
index f26973d..98e994e 100644
--- a/libgda-ui/demos/main.c
+++ b/libgda-ui/demos/main.c
@@ -799,7 +799,7 @@ main (int argc, char **argv)
/* set main context for connection */
GMainContext *context;
context = g_main_context_ref_thread_default ();
- gda_connection_set_main_context (demo_cnc, context);
+ gda_connection_set_main_context (demo_cnc, NULL, context);
g_main_context_unref (context);
g_object_set (demo_cnc, "execution-slowdown", 1000000, NULL);
diff --git a/libgda/gda-connection-private.h b/libgda/gda-connection-private.h
index ce45267..d62d72b 100644
--- a/libgda/gda-connection-private.h
+++ b/libgda/gda-connection-private.h
@@ -52,6 +52,7 @@ void gda_connection_internal_set_provider_data
GdaServerProviderConnectionData *data,
GDestroyNotify
destroy_func);
GdaServerProviderConnectionData *gda_connection_internal_get_provider_data_error (GdaConnection *cnc, GError
**error);
+void _gda_connection_internal_set_worker_thread (GdaConnection *cnc, GThread
*thread);
/*
* Connection's events
diff --git a/libgda/gda-connection.c b/libgda/gda-connection.c
index 23bf74f..d36028a 100644
--- a/libgda/gda-connection.c
+++ b/libgda/gda-connection.c
@@ -2,7 +2,7 @@
* Copyright (C) 2000 - 2001 Reinhard Müller <reinhard src gnome org>
* Copyright (C) 2000 - 2004 Rodrigo Moya <rodrigo gnome-db org>
* Copyright (C) 2001 - 2003 Gonzalo Paniagua Javier <gonzalo gnome-db org>
- * Copyright (C) 2001 - 2013 Vivien Malerba <malerba gnome-db org>
+ * Copyright (C) 2001 - 2014 Vivien Malerba <malerba gnome-db org>
* Copyright (C) 2002 Andrew Hill <andru src gnome org>
* Copyright (C) 2002 Cleber Rodrigues <cleberrrjr bol com br>
* Copyright (C) 2002 Zbigniew Chyla <cyba gnome pl>
@@ -74,9 +74,9 @@
#include <fcntl.h>
#include <unistd.h>
-static GMutex parser_mutex;
+static GMutex global_mutex;
static GdaSqlParser *internal_parser = NULL;
-static GMainContext *all_context = NULL;
+static GHashTable *all_context_hash = NULL; /* key = a #GThread, value = a #GMainContext (ref held) */
/* number of GdaConnectionEvent kept by each connection. Should be enough to avoid losing any
* event, considering that the events are reseted after each statement execution */
@@ -89,7 +89,7 @@ struct _GdaConnectionPrivate {
gchar *cnc_string;
gchar *auth_string;
- GMainContext *context;
+ GHashTable *context_hash; /* key = a #GThread, value = a #GMainContext (ref held) */
GdaMetaStore *meta_store;
@@ -104,6 +104,7 @@ struct _GdaConnectionPrivate {
GHashTable *prepared_stmts;
GdaServerProviderConnectionData *provider_data;
+ GThread *worker_thread; /* no ref held, used only for comparisons */
/* multi threading locking */
GMutex object_mutex;
@@ -404,6 +405,12 @@ gda_connection_lockable_init (GdaLockableIface *iface)
}
static void
+all_context_hash_func (GThread *key, GMainContext *context, GHashTable *copyto)
+{
+ g_hash_table_insert (copyto, key, g_main_context_ref (context));
+}
+
+static void
gda_connection_init (GdaConnection *cnc, G_GNUC_UNUSED GdaConnectionClass *klass)
{
g_return_if_fail (GDA_IS_CONNECTION (cnc));
@@ -415,10 +422,14 @@ gda_connection_init (GdaConnection *cnc, G_GNUC_UNUSED GdaConnectionClass *klass
cnc->priv->dsn = NULL;
cnc->priv->cnc_string = NULL;
cnc->priv->auth_string = NULL;
- if (all_context)
- cnc->priv->context = g_main_context_ref (all_context);
+ if (all_context_hash) {
+ g_mutex_lock (&global_mutex);
+ cnc->priv->context_hash = g_hash_table_new_full (NULL, NULL, NULL, (GDestroyNotify)
g_main_context_unref);
+ g_hash_table_foreach (all_context_hash, (GHFunc) all_context_hash_func,
cnc->priv->context_hash);
+ g_mutex_unlock (&global_mutex);
+ }
else
- cnc->priv->context = NULL;
+ cnc->priv->context_hash = NULL;
cnc->priv->auto_clear_events = TRUE;
cnc->priv->events_array_size = EVENTS_ARRAY_SIZE;
cnc->priv->events_array = g_new0 (GdaConnectionEvent*, EVENTS_ARRAY_SIZE);
@@ -429,6 +440,7 @@ gda_connection_init (GdaConnection *cnc, G_GNUC_UNUSED GdaConnectionClass *klass
cnc->priv->trans_meta_context = NULL;
cnc->priv->provider_data = NULL;
+ cnc->priv->worker_thread = NULL;
cnc->priv->exec_times = FALSE;
cnc->priv->exec_slowdown = 0;
@@ -446,9 +458,9 @@ gda_connection_dispose (GObject *object)
/* free memory */
_gda_connection_close_no_warning (cnc, NULL);
- if (cnc->priv->context) {
- g_main_context_unref (cnc->priv->context);
- cnc->priv->context = NULL;
+ if (cnc->priv->context_hash) {
+ g_hash_table_destroy (cnc->priv->context_hash);
+ cnc->priv->context_hash = NULL;
}
/* get rid of prepared statements to avoid problems */
@@ -760,6 +772,7 @@ gda_connection_get_property (GObject *object,
/**
* gda_connection_set_main_context:
* @cnc: (allow-none): a #GdaConnection, or %NULL
+ * @thread: (allow-none): the #GThread in which @context will be used, or %NULL (for the current thread)
* @context: (allow-none): a #GMainContext, or %NULL
*
* Defines the #GMainContext which will still process events while a potentially blocking operation is
performed.
@@ -768,7 +781,7 @@ gda_connection_get_property (GObject *object,
* <programlisting><![CDATA[GMainContext *context;
* cnc = gda_connection_new_...;
* context = g_main_context_ref_thread_default ();
- * gda_connection_set_main_context (cnc, context);
+ * gda_connection_set_main_context (cnc, NULL, context);
* g_main_context_unref (context);
* GError *error = NULL;
* if (! gda_connection_open (cnc, &error))
@@ -780,38 +793,46 @@ gda_connection_get_property (GObject *object,
* Since: 6.0
*/
void
-gda_connection_set_main_context (GdaConnection *cnc, GMainContext *context)
+gda_connection_set_main_context (GdaConnection *cnc, GThread *thread, GMainContext *context)
{
+ if (!thread)
+ thread = g_thread_self ();
+
+ g_mutex_lock (&global_mutex);
+
if (cnc) {
g_return_if_fail (GDA_IS_CONNECTION (cnc));
- if (cnc->priv->context == context)
- return;
-
- gda_connection_lock ((GdaLockable*) cnc);
- if (cnc->priv->context) {
- g_main_context_unref (cnc->priv->context);
- cnc->priv->context = NULL;
+ if (context) {
+ if (! cnc->priv->context_hash)
+ cnc->priv->context_hash = g_hash_table_new_full (NULL, NULL, NULL,
+ (GDestroyNotify)
g_main_context_unref);
+ g_main_context_ref (context);
+ g_hash_table_insert (cnc->priv->context_hash, thread, g_main_context_ref (context));
+ g_main_context_unref (context);
}
- if (context)
- cnc->priv->context = g_main_context_ref (context);
- gda_connection_unlock ((GdaLockable*) cnc);
+ else if (cnc->priv->context_hash)
+ g_hash_table_remove (cnc->priv->context_hash, thread);
}
else {
- if (all_context == context)
- return;
-
- if (all_context) {
- g_main_context_unref (all_context);
- all_context = NULL;
+ if (context) {
+ if (! all_context_hash)
+ all_context_hash = g_hash_table_new_full (NULL, NULL, NULL,
+ (GDestroyNotify)
g_main_context_unref);
+ g_main_context_ref (context);
+ g_hash_table_insert (all_context_hash, thread, g_main_context_ref (context));
+ g_main_context_unref (context);
}
- if (context)
- all_context = g_main_context_ref (context);
+ else if (all_context_hash)
+ g_hash_table_remove (all_context_hash, thread);
}
+
+ g_mutex_unlock (&global_mutex);
}
/**
* gda_connection_get_main_context:
* @cnc: (allow-none): a #GdaConnection, or %NULL
+ * @thread: (allow-none): the #GThread in which @context will be used, or %NULL (for the current thread)
*
* Get the #GMainContext used while a potentially blocking operation is performed, see
gda_connection_set_main_context().
* If no main context has been defined, then some function calls (for example connection opening) may block
until the
@@ -822,14 +843,28 @@ gda_connection_set_main_context (GdaConnection *cnc, GMainContext *context)
* Since: 6.0
*/
GMainContext *
-gda_connection_get_main_context (GdaConnection *cnc)
+gda_connection_get_main_context (GdaConnection *cnc, GThread *thread)
{
+ if (!thread)
+ thread = g_thread_self ();
+
+ GMainContext *context = NULL;
+
if (cnc) {
g_return_val_if_fail (GDA_IS_CONNECTION (cnc), NULL);
- return cnc->priv->context;
+ g_mutex_lock (&global_mutex);
+ if (cnc->priv->context_hash)
+ context = g_hash_table_lookup (cnc->priv->context_hash, thread);
+ g_mutex_unlock (&global_mutex);
}
- else
- return all_context;
+ else {
+ g_mutex_lock (&global_mutex);
+ if (all_context_hash)
+ context = g_hash_table_lookup (cnc->priv->context_hash, thread);
+ g_mutex_unlock (&global_mutex);
+ }
+
+ return context;
}
/*
@@ -2893,10 +2928,10 @@ gda_connection_execute_select_command (GdaConnection *cnc, const gchar *sql, GEr
|| g_str_has_prefix (sql, "SELECT"),
NULL);
- g_mutex_lock (&parser_mutex);
+ g_mutex_lock (&global_mutex);
if (!internal_parser)
internal_parser = gda_sql_parser_new ();
- g_mutex_unlock (&parser_mutex);
+ g_mutex_unlock (&global_mutex);
stmt = gda_sql_parser_parse_string (internal_parser, sql, NULL, error);
if (!stmt)
@@ -2930,10 +2965,10 @@ gda_connection_execute_non_select_command (GdaConnection *cnc, const gchar *sql,
|| GDA_IS_CONNECTION (cnc)
|| !gda_connection_is_opened (cnc), -1);
- g_mutex_lock (&parser_mutex);
+ g_mutex_lock (&global_mutex);
if (!internal_parser)
internal_parser = gda_sql_parser_new ();
- g_mutex_unlock (&parser_mutex);
+ g_mutex_unlock (&global_mutex);
stmt = gda_sql_parser_parse_string (internal_parser, sql, NULL, error);
if (!stmt)
@@ -5636,6 +5671,17 @@ gda_connection_internal_set_provider_data (GdaConnection *cnc, GdaServerProvider
gda_connection_unlock ((GdaLockable*) cnc);
}
+void
+_gda_connection_internal_set_worker_thread (GdaConnection *cnc, GThread *thread)
+{
+ g_mutex_lock (&global_mutex);
+ if (cnc->priv->worker_thread && thread)
+ g_warning ("Trying to overwriting connection's associated internal thread");
+ else
+ cnc->priv->worker_thread = thread;
+ g_mutex_unlock (&global_mutex);
+}
+
/**
* gda_connection_internal_get_provider_data_error: (skip)
* @cnc: a #GdaConnection object
@@ -5679,9 +5725,9 @@ gda_connection_get_meta_store (GdaConnection *cnc)
GdaConnection *scnc;
scnc = gda_meta_store_get_internal_connection (cnc->priv->meta_store);
if ((scnc != cnc) &&
- gda_connection_get_main_context (cnc) &&
- ! gda_connection_get_main_context (scnc))
- gda_connection_set_main_context (scnc, gda_connection_get_main_context (cnc));
+ gda_connection_get_main_context (cnc, NULL) &&
+ ! gda_connection_get_main_context (scnc, NULL))
+ gda_connection_set_main_context (scnc, NULL, gda_connection_get_main_context (cnc,
NULL));
}
g_mutex_unlock (& cnc->priv->object_mutex);
@@ -5705,18 +5751,6 @@ idle_trylock (TryLockData *data)
}
/*
- * This method is useful only in a multi threading environment (it has no effect in a
- * single thread program).
- * Locks @cnc for the current thread. If the lock can't be obtained, then the current thread
- * will be blocked until it can acquire @cnc's lock.
- *
- * The cases when the connection can't be locked are:
- * <itemizedlist>
- * <listitem><para>another thread is already using the connection</para></listitem>
- * <listitem><para>the connection can only be used by a single thread (see the
- * <link linkend="GdaConnection--thread-owner">thread-owner</link> property)</para></listitem>
- * </itemizedlist>
- *
* To avoid the thread being blocked (possibly forever if the single thread which can use the
* connection is not the current thead), then it is possible to use gda_connection_trylock() instead.
*/
@@ -5725,21 +5759,18 @@ gda_connection_lock (GdaLockable *lockable)
{
GdaConnection *cnc = (GdaConnection *) lockable;
- if (cnc->priv->provider_data) {
- /* connection is opened */
- g_assert (cnc->priv->provider_data->worker);
- if (gda_worker_thread_is_worker (cnc->priv->provider_data->worker))
- /* the sitation here is that the connection _has been_ locked by the
- * calling thread of the GdaWorker, and as we are in the worker thread
- * of the GdaWorker, we don't need to lock it again: it would be useless because
- * by desing the connection object may be modified but only by the provider code,
which
- * is Ok, and because it would require a very complex mechanism to "transfer the lock"
- * from one thread to the other */
- return;
+ if (cnc->priv->worker_thread == g_thread_self ()) {
+ /* the sitation here is that the connection _has been_ locked by the
+ * calling thread of the GdaWorker, and as we are in the worker thread
+ * of the GdaWorker, we don't need to lock it again: it would be useless because
+ * by desing the connection object may be modified but only by the provider code, which
+ * is Ok, and because it would require a very complex mechanism to "transfer the lock"
+ * from one thread to the other */
+ return;
}
GMainContext *context;
- context = gda_connection_get_main_context (cnc);
+ context = gda_connection_get_main_context (cnc, NULL);
if (context) {
if (gda_connection_trylock (lockable))
return;
@@ -5754,7 +5785,7 @@ gda_connection_lock (GdaLockable *lockable)
GSource *idle;
idle = g_idle_source_new ();
- g_source_set_priority (idle, G_PRIORITY_HIGH);
+ g_source_set_priority (idle, G_PRIORITY_DEFAULT);
g_source_attach (idle, context);
g_source_set_callback (idle, (GSourceFunc) idle_trylock, &lockdata, NULL);
g_source_unref (idle);
@@ -5777,12 +5808,9 @@ gda_connection_trylock (GdaLockable *lockable)
{
GdaConnection *cnc = (GdaConnection *) lockable;
- if (cnc->priv->provider_data) {
- /* connection is opened */
- g_assert (cnc->priv->provider_data->worker);
- if (gda_worker_thread_is_worker (cnc->priv->provider_data->worker))
- /* See gda_connection_lock() for explanations */
- return TRUE;
+ if (cnc->priv->worker_thread == g_thread_self ()) {
+ /* See gda_connection_lock() for explanations */
+ return TRUE;
}
return g_rec_mutex_trylock (& cnc->priv->rmutex);
@@ -5797,12 +5825,9 @@ gda_connection_unlock (GdaLockable *lockable)
{
GdaConnection *cnc = (GdaConnection *) lockable;
- if (cnc->priv->provider_data) {
- /* connection is opened */
- if (cnc->priv->provider_data->worker &&
- gda_worker_thread_is_worker (cnc->priv->provider_data->worker))
- /* See gda_connection_lock() for explanations */
- return;
+ if (cnc->priv->worker_thread == g_thread_self ()) {
+ /* See gda_connection_lock() for explanations */
+ return;
}
g_rec_mutex_unlock (& cnc->priv->rmutex);
diff --git a/libgda/gda-connection.h b/libgda/gda-connection.h
index dead156..149faee 100644
--- a/libgda/gda-connection.h
+++ b/libgda/gda-connection.h
@@ -268,8 +268,8 @@ gboolean gda_connection_is_opened (GdaConnection *cnc);
GdaConnectionOptions gda_connection_get_options (GdaConnection *cnc);
-void gda_connection_set_main_context (GdaConnection *cnc, GMainContext *context);
-GMainContext *gda_connection_get_main_context (GdaConnection *cnc);
+void gda_connection_set_main_context (GdaConnection *cnc, GThread *thread, GMainContext
*context);
+GMainContext *gda_connection_get_main_context (GdaConnection *cnc, GThread *thread);
GdaServerProvider *gda_connection_get_provider (GdaConnection *cnc);
const gchar *gda_connection_get_provider_name (GdaConnection *cnc);
@@ -369,6 +369,10 @@ GdaDataModel *gda_connection_get_meta_store_data (GdaConnection *cnc, Gd
GError **error, gint nb_filters, ...);
GdaDataModel *gda_connection_get_meta_store_data_v(GdaConnection *cnc, GdaConnectionMetaType
meta_type,
GList* filters, GError **error);
+
+//void gda_connection_lock_with_context (GdaConnection *cnc, GMainContext *context);
+//void gda_connection_unlock (GdaConnection *cnc);
+
G_END_DECLS
#endif
diff --git a/libgda/gda-server-provider.c b/libgda/gda-server-provider.c
index 2b9b9c3..c03f76b 100644
--- a/libgda/gda-server-provider.c
+++ b/libgda/gda-server-provider.c
@@ -514,7 +514,7 @@ GMainContext *
_gda_server_provider_get_real_main_context (GdaConnection *cnc)
{
GMainContext *context;
- context = gda_connection_get_main_context (cnc);
+ context = gda_connection_get_main_context (cnc, NULL);
if (context)
g_main_context_ref (context);
else
@@ -2132,7 +2132,7 @@ _gda_server_provider_open_connection (GdaServerProvider *provider, GdaConnection
g_return_val_if_fail ((cb_func && out_job_id) || (!cb_func && !out_job_id), FALSE);
GMainContext *context;
- context = gda_connection_get_main_context (cnc);
+ context = gda_connection_get_main_context (cnc, NULL);
if (cb_func && !context) {
g_set_error (error, GDA_CONNECTION_ERROR, GDA_CONNECTION_NO_MAIN_CONTEXT_ERROR,
"%s", _("You need to define a GMainContext using
gda_connection_set_main_context()"));
@@ -2143,6 +2143,7 @@ _gda_server_provider_open_connection (GdaServerProvider *provider, GdaConnection
GdaWorker *worker;
worker = _gda_server_provider_create_worker (provider, TRUE);
+ _gda_connection_internal_set_worker_thread (cnc, gda_worker_get_worker_thread (worker));
/* define callback if not yet done */
if (cb_func) {
@@ -2225,6 +2226,7 @@ static void
WorkerCloseConnectionData_free (WorkerCloseConnectionData *data)
{
//g_print ("%s() th %p %s\n", __FUNCTION__, g_thread_self(), gda_worker_thread_is_worker
(data->worker) ? "Thread Worker" : "NOT thread worker");
+ _gda_connection_internal_set_worker_thread (data->cnc, NULL);
gda_worker_unref (data->worker);
g_object_unref (data->cnc);
g_slice_free (WorkerCloseConnectionData, data);
diff --git a/libgda/test-cnc-exec.c b/libgda/test-cnc-exec.c
index c7b75ea..795e3e9 100644
--- a/libgda/test-cnc-exec.c
+++ b/libgda/test-cnc-exec.c
@@ -20,6 +20,7 @@
#include <glib/gstdio.h>
static guint test1 (void);
+static guint test2 (void);
int main(int argc, const char *argv[])
@@ -28,6 +29,7 @@ int main(int argc, const char *argv[])
guint nfailed = 0;
nfailed += test1 ();
+ nfailed += test2 ();
if (nfailed > 0)
g_print ("Test failed %u times\n", nfailed);
@@ -43,19 +45,25 @@ idle_incr (guint *ptr)
return TRUE;
}
+/*
+ * Pass %0 as interval to use an idle function
+ */
static void
-setup_main_context (GdaConnection *cnc, guint *ptr_to_incr)
+setup_main_context (GdaConnection *cnc, guint interval, guint *ptr_to_incr)
{
GMainContext *context;
GSource *idle;
context = g_main_context_new ();
- idle = g_idle_source_new ();
+ if (interval == 0)
+ idle = g_idle_source_new ();
+ else
+ idle = g_timeout_source_new (interval);
g_source_set_priority (idle, G_PRIORITY_DEFAULT);
g_source_attach (idle, context);
g_source_set_callback (idle, (GSourceFunc) idle_incr, ptr_to_incr, NULL);
g_source_unref (idle);
- gda_connection_set_main_context (cnc, context);
+ gda_connection_set_main_context (cnc, NULL, context);
g_main_context_unref (context);
}
@@ -84,7 +92,7 @@ test1 (void)
}
guint counter = 0;
- setup_main_context (cnc, &counter);
+ setup_main_context (cnc, 0, &counter);
/* connection open */
if (! gda_connection_open (cnc, &error)) {
@@ -140,3 +148,98 @@ test1 (void)
return 0;
}
+
+/*
+ * Test 2:
+ */
+static gpointer
+test2_th (GdaConnection *cnc)
+{
+ /* setup main context */
+ guint counter = 0;
+ setup_main_context (cnc, 100, &counter);
+
+ gda_lockable_lock (GDA_LOCKABLE (cnc));
+ g_usleep (200000);
+ gda_lockable_unlock (GDA_LOCKABLE (cnc));
+ g_thread_yield ();
+
+ gda_lockable_lock (GDA_LOCKABLE (cnc));
+ g_usleep (200000);
+ gda_lockable_unlock (GDA_LOCKABLE (cnc));
+ g_thread_yield ();
+
+ gda_lockable_lock (GDA_LOCKABLE (cnc));
+ g_usleep (200000);
+ gda_lockable_unlock (GDA_LOCKABLE (cnc));
+ g_thread_yield ();
+
+ gda_lockable_lock (GDA_LOCKABLE (cnc));
+ g_usleep (200000);
+ gda_lockable_unlock (GDA_LOCKABLE (cnc));
+
+ guint *ret;
+ ret = g_new (guint, 1);
+ *ret = counter;
+ return ret;
+}
+
+static guint
+test2 (void)
+{
+ g_print ("============= %s started =============\n", __FUNCTION__);
+ GdaConnection *cnc;
+ GError *error = NULL;
+
+ gchar *cnc_string, *fname;
+ fname = g_build_filename (ROOT_DIR, "data", NULL);
+ cnc_string = g_strdup_printf ("DB_DIR=%s;DB_NAME=sales_test", fname);
+ g_free (fname);
+ cnc = gda_connection_new_from_string ("SQLite", cnc_string, NULL,
+ GDA_CONNECTION_OPTIONS_READ_ONLY, NULL);
+ if (!cnc) {
+ g_print ("gda_connection_new_from_string([%s]) failed: %s\n", cnc_string,
+ error && error->message ? error->message : "No detail");
+ g_free (cnc_string);
+ return 1;
+ }
+
+ /* connection open */
+ if (! gda_connection_open (cnc, &error)) {
+ g_print ("gda_connection_open([%s]) failed: %s\n", cnc_string,
+ error && error->message ? error->message : "No detail");
+ g_free (cnc_string);
+ return 1;
+ }
+ g_free (cnc_string);
+
+ GThread *tha, *thb;
+
+ tha = g_thread_new ("thA", (GThreadFunc) test2_th, cnc);
+ thb = g_thread_new ("thB", (GThreadFunc) test2_th, cnc);
+ g_print ("Thread A is %p\n", tha);
+ g_print ("Thread B is %p\n", thb);
+
+ guint *counter;
+ counter = g_thread_join (tha);
+ if (*counter == 0) {
+ g_print ("Thread A: gda_connection_lock() failed: did not make GMainContext 'run'\n");
+ return 1;
+ }
+ else
+ g_print ("Thread A: Counter incremented to %u\n", *counter);
+ g_free (counter);
+
+ counter = g_thread_join (thb);
+ if (*counter == 0) {
+ g_print ("Thread B: gda_connection_lock() failed: did not make GMainContext 'run'\n");
+ return 1;
+ }
+ else
+ g_print ("Thread B: Counter incremented to %u\n", *counter);
+ g_free (counter);
+
+ g_object_unref (cnc);
+
+ return 0;
+}
diff --git a/libgda/test-cnc-meta.c b/libgda/test-cnc-meta.c
index 885ad8a..7f59930 100644
--- a/libgda/test-cnc-meta.c
+++ b/libgda/test-cnc-meta.c
@@ -55,7 +55,7 @@ setup_main_context (GdaConnection *cnc, guint *ptr_to_incr)
g_source_attach (idle, context);
g_source_set_callback (idle, (GSourceFunc) idle_incr, ptr_to_incr, NULL);
g_source_unref (idle);
- gda_connection_set_main_context (cnc, context);
+ gda_connection_set_main_context (cnc, NULL, context);
g_main_context_unref (context);
}
diff --git a/libgda/test-cnc-open.c b/libgda/test-cnc-open.c
index 1b0f66c..c3b083a 100644
--- a/libgda/test-cnc-open.c
+++ b/libgda/test-cnc-open.c
@@ -23,6 +23,7 @@ static guint test1 (void);
static guint test2 (void);
static guint test3 (void);
static guint test4 (void);
+static guint test5 (void);
int main(int argc, const char *argv[])
@@ -34,6 +35,7 @@ int main(int argc, const char *argv[])
nfailed += test2 ();
nfailed += test3 ();
nfailed += test4 ();
+ nfailed += test5 ();
g_unlink ("test-cnc-opendb.db");
@@ -63,7 +65,7 @@ setup_main_context (GdaConnection *cnc, guint *ptr_to_incr)
g_source_attach (idle, context);
g_source_set_callback (idle, (GSourceFunc) idle_incr, ptr_to_incr, NULL);
g_source_unref (idle);
- gda_connection_set_main_context (cnc, context);
+ gda_connection_set_main_context (cnc, NULL, context);
g_main_context_unref (context);
}
@@ -136,7 +138,7 @@ test2 (void)
setup_main_context (cnc, &counter);
GMainLoop *loop;
- loop = g_main_loop_new (gda_connection_get_main_context (cnc), FALSE);
+ loop = g_main_loop_new (gda_connection_get_main_context (cnc, NULL), FALSE);
guint job_id;
job_id = gda_connection_open_async (cnc, (GdaConnectionOpenFunc) test2_open_func, loop, &error);
@@ -236,7 +238,7 @@ test4 (void)
setup_main_context (cnc, &counter);
GMainLoop *loop;
- loop = g_main_loop_new (gda_connection_get_main_context (cnc), FALSE);
+ loop = g_main_loop_new (gda_connection_get_main_context (cnc, NULL), FALSE);
guint job_id;
job_id = gda_connection_open_async (cnc, (GdaConnectionOpenFunc) test4_open_func, loop, &error);
@@ -264,3 +266,66 @@ test4 (void)
return opened ? 1 : 0;
}
+
+/*
+ * Test 5: open, close and open again
+ */
+static guint
+test5 (void)
+{
+ g_print ("============= %s started =============\n", __FUNCTION__);
+ GdaConnection *cnc;
+ GError *error = NULL;
+ cnc = gda_connection_new_from_string ("SQLite", "DB_NAME=test-cnc-opendb", NULL,
+ GDA_CONNECTION_OPTIONS_AUTO_META_DATA, &error);
+
+ if (!cnc) {
+ g_print ("gda_connection_new_from_string() failed: %s\n", error && error->message ?
error->message : "No detail");
+ return 1;
+ }
+
+ guint counter = 0;
+ setup_main_context (cnc, &counter);
+
+ /* open */
+ if (! gda_connection_open (cnc, &error)) {
+ g_print ("gda_connection_open() 1 failed: %s\n", error && error->message ? error->message :
"No detail");
+ return 1;
+ }
+ if (counter == 0) {
+ g_print ("gda_connection_open() 1 failed: did not make GMainContext 'run'\n");
+ return 1;
+ }
+ else
+ g_print ("Counter incremented to %u\n", counter);
+
+ /* open */
+ counter = 0;
+ if (! gda_connection_close (cnc, &error)) {
+ g_print ("gda_connection_close() failed: %s\n", error && error->message ? error->message :
"No detail");
+ return 1;
+ }
+ if (counter == 0) {
+ g_print ("gda_connection_close() failed: did not make GMainContext 'run'\n");
+ return 1;
+ }
+ else
+ g_print ("Counter incremented to %u\n", counter);
+
+ /* open */
+ counter = 0;
+ if (! gda_connection_open (cnc, &error)) {
+ g_print ("gda_connection_open() 2 failed: %s\n", error && error->message ? error->message :
"No detail");
+ return 1;
+ }
+ if (counter == 0) {
+ g_print ("gda_connection_open() 2 failed: did not make GMainContext 'run'\n");
+ return 1;
+ }
+ else
+ g_print ("Counter incremented to %u\n", counter);
+
+ g_object_unref (cnc);
+
+ return 0;
+}
diff --git a/libgda/thread-wrapper/gda-worker.c b/libgda/thread-wrapper/gda-worker.c
index a6af91d..85c3ec7 100644
--- a/libgda/thread-wrapper/gda-worker.c
+++ b/libgda/thread-wrapper/gda-worker.c
@@ -1014,3 +1014,20 @@ gda_worker_thread_is_worker (GdaWorker *worker)
g_return_val_if_fail (worker, NULL);
return worker->worker_thread == g_thread_self () ? TRUE : FALSE;
}
+
+/**
+ * gda_worker_get_worker_thread:
+ * @worker: a #GdaWorker
+ *
+ * Get a pointer to @worker's inner worker thread
+ *
+ * Returns: (transfer none): the #GThread
+ *
+ * Since: 6.0
+ */
+GThread *
+gda_worker_get_worker_thread (GdaWorker *worker)
+{
+ g_return_val_if_fail (worker, NULL);
+ return worker->worker_thread;
+}
diff --git a/libgda/thread-wrapper/gda-worker.h b/libgda/thread-wrapper/gda-worker.h
index a34b44c..f1451cb 100644
--- a/libgda/thread-wrapper/gda-worker.h
+++ b/libgda/thread-wrapper/gda-worker.h
@@ -106,6 +106,7 @@ gboolean gda_worker_set_callback (GdaWorker *worker, GMainContext *context, Gd
gpointer user_data, GError **error);
gboolean gda_worker_thread_is_worker (GdaWorker *worker);
+GThread *gda_worker_get_worker_thread (GdaWorker *worker);
G_END_DECLS
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]