[evolution] Bug 788156 - Remote content download slows down message preview
- From: Milan Crha <mcrha src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [evolution] Bug 788156 - Remote content download slows down message preview
- Date: Tue, 3 Oct 2017 09:42:28 +0000 (UTC)
commit aff71954924b8e428f5bc54c0072bae1e5a5afde
Author: Milan Crha <mcrha redhat com>
Date: Tue Oct 3 11:43:19 2017 +0200
Bug 788156 - Remote content download slows down message preview
src/e-util/e-content-request.c | 53 +++++++++------
src/e-util/e-simple-async-result.c | 99 +++++++++++++++++++++++++++
src/e-util/e-simple-async-result.h | 12 +++-
src/e-util/e-web-view.c | 38 ++++++++++-
src/modules/webkit-editor/e-webkit-editor.c | 5 +-
src/shell/main.c | 1 +
6 files changed, 185 insertions(+), 23 deletions(-)
---
diff --git a/src/e-util/e-content-request.c b/src/e-util/e-content-request.c
index 3e95094..9be6e09 100644
--- a/src/e-util/e-content-request.c
+++ b/src/e-util/e-content-request.c
@@ -20,7 +20,8 @@
#include <glib.h>
#include <glib-object.h>
-#include <gio/gio.h>
+
+#include "e-simple-async-result.h"
#include "e-content-request.h"
@@ -90,6 +91,8 @@ typedef struct _ThreadData
GInputStream *out_stream;
gint64 out_stream_length;
gchar *out_mime_type;
+ GError *error;
+ gboolean success;
} ThreadData;
static void
@@ -102,29 +105,27 @@ thread_data_free (gpointer ptr)
g_clear_object (&td->requester);
g_free (td->uri);
g_free (td->out_mime_type);
+ g_clear_error (&td->error);
g_free (td);
}
}
static void
-content_request_process_thread (GTask *task,
+content_request_process_thread (ESimpleAsyncResult *result,
gpointer source_object,
- gpointer task_data,
GCancellable *cancellable)
{
- ThreadData *td = task_data;
- GError *local_error = NULL;
+ ThreadData *td;
+ g_return_if_fail (E_IS_SIMPLE_ASYNC_RESULT (result));
g_return_if_fail (E_IS_CONTENT_REQUEST (source_object));
+
+ td = e_simple_async_result_get_user_data (result);
g_return_if_fail (td != NULL);
- if (!e_content_request_process_sync (E_CONTENT_REQUEST (source_object),
+ td->success = e_content_request_process_sync (E_CONTENT_REQUEST (source_object),
td->uri, td->requester, &td->out_stream, &td->out_stream_length, &td->out_mime_type,
- cancellable, &local_error)) {
- g_task_return_error (task, local_error);
- } else {
- g_task_return_boolean (task, TRUE);
- }
+ cancellable, &td->error);
}
void
@@ -135,21 +136,27 @@ e_content_request_process (EContentRequest *request,
GAsyncReadyCallback callback,
gpointer user_data)
{
- GTask *task;
ThreadData *td;
+ ESimpleAsyncResult *result;
+ gboolean is_http;
g_return_if_fail (E_IS_CONTENT_REQUEST (request));
g_return_if_fail (uri != NULL);
g_return_if_fail (G_IS_OBJECT (requester));
+ is_http = g_ascii_strncasecmp (uri, "http", 4) == 0 ||
+ g_ascii_strncasecmp (uri, "evo-http", 8) == 0;
+
td = g_new0 (ThreadData, 1);
td->uri = g_strdup (uri);
td->requester = g_object_ref (requester);
- task = g_task_new (request, cancellable, callback, user_data);
- g_task_set_task_data (task, td, thread_data_free);
- g_task_run_in_thread (task, content_request_process_thread);
- g_object_unref (task);
+ result = e_simple_async_result_new (G_OBJECT (request), callback, user_data,
e_content_request_process);
+
+ e_simple_async_result_set_user_data (result, td, thread_data_free);
+ e_simple_async_result_run_in_thread (result, is_http ? G_PRIORITY_LOW : G_PRIORITY_DEFAULT,
content_request_process_thread, cancellable);
+
+ g_object_unref (result);
}
gboolean
@@ -162,18 +169,24 @@ e_content_request_process_finish (EContentRequest *request,
{
ThreadData *td;
- g_return_val_if_fail (g_task_is_valid (result, request), FALSE);
+ g_return_val_if_fail (g_async_result_is_tagged (result, e_content_request_process), FALSE);
g_return_val_if_fail (E_IS_CONTENT_REQUEST (request), FALSE);
- g_return_val_if_fail (G_IS_TASK (result), FALSE);
+ g_return_val_if_fail (E_IS_SIMPLE_ASYNC_RESULT (result), FALSE);
g_return_val_if_fail (out_stream != NULL, FALSE);
g_return_val_if_fail (out_stream_length != NULL, FALSE);
g_return_val_if_fail (out_mime_type != NULL, FALSE);
- td = g_task_get_task_data (G_TASK (result));
+ td = e_simple_async_result_get_user_data (E_SIMPLE_ASYNC_RESULT (result));
g_return_val_if_fail (td != NULL, FALSE);
- if (!g_task_propagate_boolean (G_TASK (result), error))
+ if (td->error || !td->success) {
+ if (td->error) {
+ g_propagate_error (error, td->error);
+ td->error = NULL;
+ }
+
return FALSE;
+ }
*out_stream = td->out_stream;
*out_stream_length = td->out_stream_length;
diff --git a/src/e-util/e-simple-async-result.c b/src/e-util/e-simple-async-result.c
index bb9e87f..5959a69 100644
--- a/src/e-util/e-simple-async-result.c
+++ b/src/e-util/e-simple-async-result.c
@@ -206,6 +206,87 @@ e_simple_async_result_get_op_pointer (ESimpleAsyncResult *result)
return result->priv->op_pointer;
}
+static GThreadPool *thread_pool = NULL;
+static GThreadPool *low_prio_thread_pool = NULL;
+G_LOCK_DEFINE_STATIC (thread_pool);
+
+typedef struct _ThreadData {
+ ESimpleAsyncResult *result;
+ gint io_priority;
+ ESimpleAsyncResultThreadFunc func;
+ GCancellable *cancellable;
+} ThreadData;
+
+static gint
+e_simple_async_result_thread_pool_sort_func (gconstpointer ptra,
+ gconstpointer ptrb,
+ gpointer user_data)
+{
+ const ThreadData *tda = ptra, *tdb = ptrb;
+
+ if (!tda || !tdb)
+ return 0;
+
+ return tda->io_priority < tdb->io_priority ? -1 :
+ tda->io_priority > tdb->io_priority ? 1 : 0;
+}
+
+static void
+e_simple_async_result_thread (gpointer data,
+ gpointer user_data)
+{
+ ThreadData *td = data;
+
+ g_return_if_fail (td != NULL);
+ g_return_if_fail (E_IS_SIMPLE_ASYNC_RESULT (td->result));
+ g_return_if_fail (td->func != NULL);
+
+ td->func (td->result,
+ g_async_result_get_source_object (G_ASYNC_RESULT (td->result)),
+ td->cancellable);
+
+ e_simple_async_result_complete_idle (td->result);
+
+ g_clear_object (&td->result);
+ g_clear_object (&td->cancellable);
+ g_free (td);
+}
+
+void
+e_simple_async_result_run_in_thread (ESimpleAsyncResult *result,
+ gint io_priority,
+ ESimpleAsyncResultThreadFunc func,
+ GCancellable *cancellable)
+{
+ ThreadData *td;
+
+ g_return_if_fail (E_IS_SIMPLE_ASYNC_RESULT (result));
+ g_return_if_fail (func != NULL);
+
+ td = g_new0 (ThreadData, 1);
+ td->result = g_object_ref (result);
+ td->io_priority = io_priority;
+ td->func = func;
+ td->cancellable = cancellable ? g_object_ref (cancellable) : NULL;
+
+ G_LOCK (thread_pool);
+
+ if (!thread_pool) {
+ thread_pool = g_thread_pool_new (e_simple_async_result_thread, NULL, 10, FALSE, NULL);
+ g_thread_pool_set_sort_function (thread_pool, e_simple_async_result_thread_pool_sort_func,
NULL);
+
+ low_prio_thread_pool = g_thread_pool_new (e_simple_async_result_thread, NULL, 10, FALSE,
NULL);
+ g_thread_pool_set_sort_function (low_prio_thread_pool,
e_simple_async_result_thread_pool_sort_func, NULL);
+ }
+
+ if (io_priority >= G_PRIORITY_LOW)
+ g_thread_pool_push (low_prio_thread_pool, td, NULL);
+ else
+ g_thread_pool_push (thread_pool, td, NULL);
+
+ G_UNLOCK (thread_pool);
+}
+
void
e_simple_async_result_complete (ESimpleAsyncResult *result)
{
@@ -238,3 +319,21 @@ e_simple_async_result_complete_idle (ESimpleAsyncResult *result)
g_idle_add (result_complete_idle_cb, g_object_ref (result));
}
+
+void
+e_simple_async_result_free_global_memory (void)
+{
+ G_LOCK (thread_pool);
+
+ if (thread_pool) {
+ g_thread_pool_free (thread_pool, TRUE, FALSE);
+ thread_pool = NULL;
+ }
+
+ if (low_prio_thread_pool) {
+ g_thread_pool_free (low_prio_thread_pool, TRUE, FALSE);
+ low_prio_thread_pool = NULL;
+ }
+
+ G_UNLOCK (thread_pool);
+}
diff --git a/src/e-util/e-simple-async-result.h b/src/e-util/e-simple-async-result.h
index d2a5699..8319e96 100644
--- a/src/e-util/e-simple-async-result.h
+++ b/src/e-util/e-simple-async-result.h
@@ -48,6 +48,10 @@ typedef struct _ESimpleAsyncResult ESimpleAsyncResult;
typedef struct _ESimpleAsyncResultClass ESimpleAsyncResultClass;
typedef struct _ESimpleAsyncResultPrivate ESimpleAsyncResultPrivate;
+typedef void (* ESimpleAsyncResultThreadFunc) (ESimpleAsyncResult *result,
+ gpointer source_object,
+ GCancellable *cancellable);
+
/**
* ESimpleAsyncResult:
*
@@ -83,10 +87,16 @@ void e_simple_async_result_set_op_pointer
gpointer ptr);
gpointer e_simple_async_result_get_op_pointer
(ESimpleAsyncResult *result);
+void e_simple_async_result_run_in_thread
+ (ESimpleAsyncResult *result,
+ gint io_priority,
+ ESimpleAsyncResultThreadFunc func,
+ GCancellable *cancellable);
void e_simple_async_result_complete (ESimpleAsyncResult *result);
void e_simple_async_result_complete_idle
(ESimpleAsyncResult *result);
-
+void e_simple_async_result_free_global_memory
+ (void);
G_END_DECLS
diff --git a/src/e-util/e-web-view.c b/src/e-util/e-web-view.c
index f13d14c..8b1500a 100644
--- a/src/e-util/e-web-view.c
+++ b/src/e-util/e-web-view.c
@@ -99,6 +99,8 @@ struct _EWebViewPrivate {
gboolean need_input;
guint web_extension_need_input_changed_signal_id;
+
+ GCancellable *load_cancellable;
};
struct _AsyncContext {
@@ -962,6 +964,11 @@ web_view_dispose (GObject *object)
priv = E_WEB_VIEW_GET_PRIVATE (object);
+ if (priv->load_cancellable) {
+ g_cancellable_cancel (priv->load_cancellable);
+ g_clear_object (&priv->load_cancellable);
+ }
+
if (priv->font_name_changed_handler_id > 0) {
g_signal_handler_disconnect (
priv->font_settings,
@@ -1097,6 +1104,7 @@ static void
web_view_process_uri_request_cb (WebKitURISchemeRequest *request,
gpointer user_data)
{
+ EWebView *web_view = NULL;
EContentRequest *content_request = user_data;
const gchar *uri;
gchar *redirect_to_uri = NULL;
@@ -1140,9 +1148,11 @@ web_view_process_uri_request_cb (WebKitURISchemeRequest *request,
return;
}
+
+ web_view = E_WEB_VIEW (requester);
}
- e_content_request_process (content_request, uri, requester, NULL,
+ e_content_request_process (content_request, uri, requester, web_view ?
web_view->priv->load_cancellable : NULL,
web_view_uri_request_done_cb, g_object_ref (request));
g_free (redirect_to_uri);
@@ -1255,6 +1265,21 @@ web_view_constructed (GObject *object)
web_view_set_find_controller (E_WEB_VIEW (object));
}
+static void
+e_web_view_replace_load_cancellable (EWebView *web_view,
+ gboolean create_new)
+{
+ g_return_if_fail (E_IS_WEB_VIEW (web_view));
+
+ if (web_view->priv->load_cancellable) {
+ g_cancellable_cancel (web_view->priv->load_cancellable);
+ g_clear_object (&web_view->priv->load_cancellable);
+ }
+
+ if (create_new)
+ web_view->priv->load_cancellable = g_cancellable_new ();
+}
+
static gboolean
web_view_scroll_event (GtkWidget *widget,
GdkEventScroll *event)
@@ -1473,6 +1498,7 @@ web_view_popup_event (EWebView *web_view,
static void
web_view_stop_loading (EWebView *web_view)
{
+ e_web_view_replace_load_cancellable (web_view, FALSE);
webkit_web_view_stop_loading (WEBKIT_WEB_VIEW (web_view));
}
@@ -2528,6 +2554,8 @@ e_web_view_init (EWebView *web_view)
e_plugin_ui_enable_manager (ui_manager, id);
web_view->priv->element_clicked_cbs = g_hash_table_new_full (g_str_hash, g_str_equal, g_free,
(GDestroyNotify) g_ptr_array_unref);
+
+ web_view->priv->load_cancellable = NULL;
}
GtkWidget *
@@ -2543,6 +2571,8 @@ e_web_view_clear (EWebView *web_view)
{
g_return_if_fail (E_IS_WEB_VIEW (web_view));
+ e_web_view_replace_load_cancellable (web_view, FALSE);
+
webkit_web_view_load_html (
WEBKIT_WEB_VIEW (web_view),
"<html>"
@@ -2563,6 +2593,8 @@ e_web_view_load_string (EWebView *web_view,
class = E_WEB_VIEW_GET_CLASS (web_view);
g_return_if_fail (class->load_string != NULL);
+ e_web_view_replace_load_cancellable (web_view, TRUE);
+
class->load_string (web_view, string);
}
@@ -2577,6 +2609,8 @@ e_web_view_load_uri (EWebView *web_view,
class = E_WEB_VIEW_GET_CLASS (web_view);
g_return_if_fail (class->load_uri != NULL);
+ e_web_view_replace_load_cancellable (web_view, TRUE);
+
class->load_uri (web_view, uri);
}
@@ -2626,6 +2660,8 @@ e_web_view_reload (EWebView *web_view)
{
g_return_if_fail (E_IS_WEB_VIEW (web_view));
+ e_web_view_replace_load_cancellable (web_view, TRUE);
+
webkit_web_view_reload (WEBKIT_WEB_VIEW (web_view));
}
diff --git a/src/modules/webkit-editor/e-webkit-editor.c b/src/modules/webkit-editor/e-webkit-editor.c
index c923a9c..511503e 100644
--- a/src/modules/webkit-editor/e-webkit-editor.c
+++ b/src/modules/webkit-editor/e-webkit-editor.c
@@ -5092,6 +5092,7 @@ static void
webkit_editor_process_uri_request_cb (WebKitURISchemeRequest *request,
gpointer user_data)
{
+ EWebKitEditor *wk_editor;
EContentRequest *content_request = user_data;
const gchar *uri;
GObject *requester;
@@ -5114,7 +5115,9 @@ webkit_editor_process_uri_request_cb (WebKitURISchemeRequest *request,
g_return_if_fail (e_content_request_can_process_uri (content_request, uri));
- e_content_request_process (content_request, uri, requester, NULL,
+ wk_editor = E_IS_WEBKIT_EDITOR (requester) ? E_WEBKIT_EDITOR (requester) : NULL;
+
+ e_content_request_process (content_request, uri, requester, wk_editor ? wk_editor->priv->cancellable
: NULL,
webkit_editor_uri_request_done_cb, g_object_ref (request));
}
diff --git a/src/shell/main.c b/src/shell/main.c
index 17fd8a9..2863d35 100644
--- a/src/shell/main.c
+++ b/src/shell/main.c
@@ -689,6 +689,7 @@ exit:
e_util_cleanup_settings ();
e_spell_checker_free_global_memory ();
+ e_simple_async_result_free_global_memory ();
return 0;
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]