[tracker/async-get-connection: 5/5] libtracker-sparql: Added locking to sync/async connection_get() methods



commit 25073e54a568981d88ac5dd74491a7d9011f908b
Author: Martyn Russell <martyn lanedo com>
Date:   Wed Sep 29 16:27:06 2010 +0100

    libtracker-sparql: Added locking to sync/async connection_get() methods

 src/libtracker-sparql/tracker-connection.vala |   24 +++++++---
 tests/libtracker-sparql/tracker-test.c        |   59 +++++++++++++++++++++++++
 2 files changed, 75 insertions(+), 8 deletions(-)
---
diff --git a/src/libtracker-sparql/tracker-connection.vala b/src/libtracker-sparql/tracker-connection.vala
index 333f5f7..d67e361 100644
--- a/src/libtracker-sparql/tracker-connection.vala
+++ b/src/libtracker-sparql/tracker-connection.vala
@@ -83,56 +83,63 @@ public abstract class Tracker.Sparql.Connection : Object {
 	static bool direct_only;
 	static weak Connection? singleton;
 	static bool log_initialized;
+	static StaticMutex door;
 
 	private static new Connection get_internal (bool is_direct_only = false, Cancellable? cancellable = null) throws Sparql.Error, IOError {
+		door.lock ();
+
 		if (singleton != null) {
 			assert (direct_only == is_direct_only);
+			door.unlock ();
 			return singleton;
 		}
 
 		log_init ();
 
-		if (cancellable != null && cancellable.is_cancelled ()) {
-			throw new IOError.CANCELLED ("Operation was cancelled");
-		}
-
 		/* the True is to assert that direct only is required */
 		Connection result = new Backend (is_direct_only);
 		result.init ();
 
 		if (cancellable != null && cancellable.is_cancelled ()) {
+			door.unlock ();
 			throw new IOError.CANCELLED ("Operation was cancelled");
 		}
 
 		direct_only = is_direct_only;
 		singleton = result;
 		result.add_weak_pointer ((void**) (&singleton));
+
+		door.unlock ();
+
 		return singleton;
 	}
 
 	private async static new Connection get_internal_async (bool is_direct_only = false, Cancellable? cancellable = null) throws Sparql.Error, IOError {
+		door.lock ();
+
 		if (singleton != null) {
 			assert (direct_only == is_direct_only);
+			door.unlock ();
 			return singleton;
 		}
 
 		log_init ();
 
-		if (cancellable != null && cancellable.is_cancelled ()) {
-			throw new IOError.CANCELLED ("Operation was cancelled");
-		}
-
 		/* the True is to assert that direct only is required */
 		Connection result = new Backend (is_direct_only);
 		yield result.init_async ();
 
 		if (cancellable != null && cancellable.is_cancelled ()) {
+			door.unlock ();
 			throw new IOError.CANCELLED ("Operation was cancelled");
 		}
 
 		direct_only = is_direct_only;
 		singleton = result;
 		result.add_weak_pointer ((void**) (&singleton));
+
+		door.unlock ();
+
 		return singleton;
 	}
 
@@ -147,6 +154,7 @@ public abstract class Tracker.Sparql.Connection : Object {
 	 * object when no longer used.
 	 */
 	public async static new Connection get_async (Cancellable? cancellable = null) throws Sparql.Error, IOError {
+
 		return yield get_internal_async (false, cancellable);
 	}
 
diff --git a/tests/libtracker-sparql/tracker-test.c b/tests/libtracker-sparql/tracker-test.c
index 7be6933..073cbcc 100644
--- a/tests/libtracker-sparql/tracker-test.c
+++ b/tests/libtracker-sparql/tracker-test.c
@@ -221,6 +221,61 @@ test_tracker_sparql_cursor_next_async (void)
 	test_tracker_sparql_cursor_next_async_query (0);
 }
 
+static void
+test_tracker_sparql_connection_locking_sync (void)
+{
+	TrackerSparqlConnection *c1, *c2, *c3;
+
+	c1 = tracker_sparql_connection_get (NULL, NULL);
+	c2 = tracker_sparql_connection_get (NULL, NULL);
+	c3 = tracker_sparql_connection_get (NULL, NULL);
+	g_assert (c1 == c2);
+	g_assert (c2 == c3);
+
+	g_object_unref (c1);
+	g_object_unref (c2);
+	g_object_unref (c3);
+}
+
+static TrackerSparqlConnection *c1 = NULL;
+static TrackerSparqlConnection *c2 = NULL;
+static TrackerSparqlConnection *c3 = NULL;
+
+static void
+test_tracker_sparql_connection_locking_async_cb (GObject      *source,
+                                                 GAsyncResult *result,
+                                                 gpointer      user_data)
+{
+	TrackerSparqlConnection *connection;
+	TrackerSparqlConnection *connection_waiting;
+	GError *error = NULL;
+
+	g_assert (result != NULL);
+	connection = tracker_sparql_connection_get_finish (result, &error);
+	g_assert_no_error (error);
+	g_assert (connection != NULL);
+
+	if (!c1) {
+		g_message ("GOT connection #1, waiting connection:%p (expecting NULL)", user_data);
+		c1 = connection;
+	} else if (!c2) {
+		g_message ("GOT connection #2, waiting connection:%p (expecting NULL)", user_data);
+		c2 = connection;
+	}
+
+	connection_waiting = user_data;
+	g_assert (connection_waiting == NULL);
+}
+
+static void
+test_tracker_sparql_connection_locking_async (void)
+{
+	tracker_sparql_connection_get_async (NULL, test_tracker_sparql_connection_locking_async_cb, c2);
+	tracker_sparql_connection_get_async (NULL, test_tracker_sparql_connection_locking_async_cb, c3);
+	c3 = tracker_sparql_connection_get (NULL, NULL);
+	g_assert (c3 != NULL);
+}
+
 #endif
 
 gint
@@ -248,6 +303,10 @@ main (gint argc, gchar **argv)
 	                 test_tracker_sparql_escape_string);
 	g_test_add_func ("/libtracker-sparql/tracker/tracker_sparql_escape_uri_vprintf",
 	                 test_tracker_sparql_escape_uri_vprintf);
+	g_test_add_func ("/libtracker-sparql/tracker/tracker_sparql_connection_locking_sync",
+	                 test_tracker_sparql_connection_locking_sync);
+	g_test_add_func ("/libtracker-sparql/tracker/tracker_sparql_connection_locking_async",
+	                 test_tracker_sparql_connection_locking_async);
 #if HAVE_TRACKER_FTS
 	g_test_add_func ("/libtracker-sparql/tracker/tracker_sparql_cursor_next_async",
 	                 test_tracker_sparql_cursor_next_async);



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]