[Evolution-hackers] Patch: SOUP MT support



Hi

The following patch adds some basic MT support to libsoup. It's against
v1.99.24. It allows the use of "soup_message_queue" in MT applications.
I'm not sure how to fix "soup_message_send", since it calls
g_main_iteration(TRUE), which blocks forever if it's called from an other
thread.

Is there an official homepage for libsoup development?

Thanks

Jan-Marek Glogowski


diff -burN -X develop/excl-diff -x get -x libsoup-ssl-proxy libsoup-1.99.24/libsoup/soup-message.c libsoup-1.99.24-jmg/libsoup/soup-message.c
--- libsoup-1.99.24/libsoup/soup-message.c	2003-06-26 18:27:03.000000000 +0200
+++ libsoup-1.99.24-jmg/libsoup/soup-message.c	2003-09-22 07:35:41.000000000 +0200
@@ -48,6 +48,8 @@

 	ret->priv->http_version = SOUP_HTTP_1_1;

+	ret->refcnt = 1;
+
 	soup_message_set_context (ret, context);

 	return ret;
@@ -252,7 +254,13 @@
 {
 	g_return_if_fail (req != NULL);

-	soup_message_cleanup (req);
+	/*
+	 * Make sure we don't free the message
+	 * inside soup_message_cleanup
+	 */
+	soup_message_ref(req);
+
+	soup_message_cleanup(req);

 	finalize_message (req);
 }
@@ -273,6 +281,12 @@
 	g_return_if_fail (req != NULL);

 	/*
+	 * Make sure we don't free the message
+	 * inside soup_message_cleanup
+	 */
+	soup_message_ref (req);
+
+	/*
 	 * Make sure we don't have some icky recursion if the callback
 	 * runs the main loop, and the connection has some data or error
 	 * which causes the callback to be run again.
@@ -282,9 +296,15 @@
 	if (req->priv->callback) {
 		(*req->priv->callback) (req, req->priv->user_data);

-		if (req->status != SOUP_STATUS_QUEUED)
+		if (req->status != SOUP_STATUS_QUEUED) {
 			finalize_message (req);
+
+			// Finalize frees the message so skip unref
+			return;
+		}
 	}
+
+	soup_message_unref (req);
 }

 /**
@@ -1213,3 +1233,20 @@
 	msg->errorclass = SOUP_ERROR_CLASS_HANDLER;
 	msg->errorphrase = g_strdup (errphrase);
 }
+
+void
+soup_message_ref (SoupMessage *msg)
+{
+	g_return_if_fail (msg != NULL);
+
+	msg->refcnt++;
+}
+
+void
+soup_message_unref (SoupMessage *msg)
+{
+	g_return_if_fail (msg != NULL);
+
+	if (msg->refcnt > 1) { msg->refcnt--; }
+	else { soup_message_free(msg); }
+}
diff -burN -X develop/excl-diff -x get -x libsoup-ssl-proxy libsoup-1.99.24/libsoup/soup-message.h libsoup-1.99.24-jmg/libsoup/soup-message.h
--- libsoup-1.99.24/libsoup/soup-message.h	2002-11-18 16:26:19.000000000 +0100
+++ libsoup-1.99.24-jmg/libsoup/soup-message.h	2003-09-22 06:16:48.000000000 +0200
@@ -59,6 +59,8 @@

 	SoupDataBuffer      response;
 	GHashTable         *response_headers;
+
+	guint               refcnt;
 };

 #define SOUP_MESSAGE_IS_ERROR(_msg)                            \
@@ -82,6 +84,10 @@

 void           soup_message_free                (SoupMessage       *req);

+void           soup_message_ref                 (SoupMessage       *msg);
+
+void           soup_message_unref               (SoupMessage       *msg);
+
 void           soup_message_cancel              (SoupMessage       *req);

 SoupErrorClass soup_message_send                (SoupMessage       *msg);
diff -burN -X develop/excl-diff -x get -x libsoup-ssl-proxy libsoup-1.99.24/libsoup/soup-queue.c libsoup-1.99.24-jmg/libsoup/soup-queue.c
--- libsoup-1.99.24/libsoup/soup-queue.c	2003-09-22 07:35:37.000000000 +0200
+++ libsoup-1.99.24-jmg/libsoup/soup-queue.c	2003-09-24 01:49:17.000000000 +0200
@@ -33,6 +33,7 @@
 static GSList *soup_active_requests = NULL, *soup_active_request_next = NULL;

 static guint soup_queue_idle_tag = 0;
+static GMutex *mutex = NULL;

 static void
 soup_debug_print_a_header (gchar *key, gchar *val, gpointer not_used)
@@ -685,15 +686,26 @@
 void
 soup_queue_add_request (SoupMessage *req)
 {
-	soup_active_requests = g_slist_prepend (soup_active_requests, req);
+	soup_message_ref(req);
+	soup_active_requests =
+		g_slist_prepend (soup_active_requests, req);
 }

 void
 soup_queue_remove_request (SoupMessage *req)
 {
+	GSList *list;
+
 	if (soup_active_request_next && soup_active_request_next->data == req)
 		soup_queue_next_request ();
-	soup_active_requests = g_slist_remove (soup_active_requests, req);
+
+	g_mutex_lock(mutex);
+	if ((list = g_slist_find(soup_active_requests, req)) != NULL) {
+		soup_active_requests =
+			g_slist_remove_link(soup_active_requests, list);
+		soup_message_unref(req);
+	}
+	g_mutex_unlock(mutex);
 }

 SoupMessage *
@@ -730,13 +742,22 @@
 static gboolean
 soup_idle_handle_new_requests (gpointer unused)
 {
-	SoupMessage *req = soup_queue_first_request ();
+	SoupMessage *req;
+	GSList *first;

-	for (; req; req = soup_queue_next_request ()) {
+	g_mutex_lock(mutex);
+	req = soup_queue_first_request ();
+	if (req == NULL)
+		{ goto handle_exit; }
+	first = soup_active_requests;
+	soup_message_ref(req);
+	g_mutex_unlock(mutex);
+
+	while (1) {
 		SoupContext *ctx, *proxy;

 		if (req->status != SOUP_STATUS_QUEUED)
-			continue;
+			goto handle_next_message;

 		proxy = soup_get_proxy ();
 		ctx = proxy ? proxy : req->context;
@@ -758,21 +779,40 @@
 			if (connect_tag && request_in_progress (req))
 				req->priv->connect_tag = connect_tag;
 		}
+
+handle_next_message:
+		g_mutex_lock(mutex);
+		soup_message_unref(req);
+		req = soup_queue_next_request();
+		if (req == NULL) {
+			if (first == soup_active_requests)
+				break;
+			else {
+				first = soup_active_requests;
+				req = soup_queue_first_request();
+				if (req == NULL)
+					break;
+			}
+		}
+		soup_message_ref(req);
+		g_mutex_unlock(mutex);
 	}

+handle_exit:
 	soup_queue_idle_tag = 0;
+
+	g_mutex_unlock(mutex);
+
 	return FALSE;
 }

 static void
 soup_queue_initialize (void)
 {
-	if (!soup_initialized)
+	if (!soup_initialized) {
 		soup_load_config (NULL);
-
-	if (!soup_queue_idle_tag)
-		soup_queue_idle_tag =
-			g_idle_add (soup_idle_handle_new_requests, NULL);
+		mutex = g_mutex_new();
+	}
 }

 void
@@ -829,9 +869,16 @@

 	req->status = SOUP_STATUS_QUEUED;

+	soup_queue_initialize ();
+
 	soup_queue_add_request (req);

-	soup_queue_initialize ();
+	g_mutex_lock(mutex);
+	if (soup_queue_idle_tag == 0) {
+		soup_queue_idle_tag =
+			g_idle_add (soup_idle_handle_new_requests, NULL);
+	}
+	g_mutex_unlock(mutex);
 }

 /**
@@ -857,4 +904,7 @@
 		soup_message_cancel (req);

 	soup_connection_purge_idle ();
+
+	g_mutex_free(mutex);
+	mutex = NULL;
 }



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