[geary/wip/362-utf8-attachments: 5/8] Reduce blocking the main thread when sending email
- From: Michael Gratton <mjog src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [geary/wip/362-utf8-attachments: 5/8] Reduce blocking the main thread when sending email
- Date: Fri, 19 Jul 2019 10:53:04 +0000 (UTC)
commit 3dc5476fcda56bd89ab7fb653b281241a3f3e004
Author: Michael Gratton <mike vee net>
Date: Fri Jul 19 16:49:43 2019 +1000
Reduce blocking the main thread when sending email
Make guessing charset and encoding work on a background thread when
constructing RFC822.Message instances from ComposedEmail.
src/engine/rfc822/rfc822-message.vala | 8 ++++--
src/engine/rfc822/rfc822-utils.vala | 47 ++++++++++++++++++++++++-----------
2 files changed, 38 insertions(+), 17 deletions(-)
---
diff --git a/src/engine/rfc822/rfc822-message.vala b/src/engine/rfc822/rfc822-message.vala
index 0550aa80..6b335bd5 100644
--- a/src/engine/rfc822/rfc822-message.vala
+++ b/src/engine/rfc822/rfc822-message.vala
@@ -1070,12 +1070,16 @@ public class Geary.RFC822.Message : BaseObject, EmailHeaderSet {
throws GLib.Error {
GMime.Stream content_stream = new GMime.StreamMem.with_buffer(content);
if (charset == null) {
- charset = Geary.RFC822.Utils.get_best_charset(content_stream);
+ charset = yield Utils.get_best_charset(content_stream, cancellable);
}
GMime.StreamFilter filter_stream = new GMime.StreamFilter(content_stream);
filter_stream.add(new GMime.FilterCharset(UTF8_CHARSET, charset));
if (encoding == null) {
- encoding = Geary.RFC822.Utils.get_best_encoding(filter_stream);
+ encoding = yield Utils.get_best_encoding(
+ filter_stream,
+ GMime.EncodingConstraint.7BIT,
+ cancellable
+ );
}
if (is_flowed && encoding == GMime.ContentEncoding.BASE64) {
// Base64-encoded text needs to have CR's added after LF's
diff --git a/src/engine/rfc822/rfc822-utils.vala b/src/engine/rfc822/rfc822-utils.vala
index dfa4180e..55a92061 100644
--- a/src/engine/rfc822/rfc822-utils.vala
+++ b/src/engine/rfc822/rfc822-utils.vala
@@ -254,37 +254,54 @@ public string to_preview_text(string? text, TextFormat format) {
/**
* Uses a GMime.FilterBest to determine the best charset.
*
- * WARNING: This call does not perform async I/O, meaning it will loop on the
- * stream without relinquishing control to the event loop. Use with
- * caution.
+ * This may require processing the entire stream, so occurs in a
+ * background thread.
*/
-public string get_best_charset(GMime.Stream in_stream) {
+public async string get_best_charset(GMime.Stream in_stream,
+ GLib.Cancellable? cancellable)
+ throws GLib.Error {
GMime.FilterBest filter = new GMime.FilterBest(
GMime.FilterBestFlags.CHARSET
);
- GMime.StreamFilter out_stream = new GMime.StreamFilter(new GMime.StreamNull());
+ GMime.StreamFilter out_stream = new GMime.StreamFilter(
+ new GMime.StreamNull()
+ );
out_stream.add(filter);
- in_stream.write_to_stream(out_stream);
- in_stream.reset();
+
+ yield Nonblocking.Concurrent.global.schedule_async(() => {
+ in_stream.write_to_stream(out_stream);
+ in_stream.reset();
+ },
+ cancellable
+ );
return filter.charset();
}
/**
* Uses a GMime.FilterBest to determine the best encoding.
*
- * WARNING: This call does not perform async I/O, meaning it will loop on the
- * stream without relinquishing control to the event loop. Use with
- * caution.
+ * This may require processing the entire stream, so occurs in a
+ * background thread.
*/
-public GMime.ContentEncoding get_best_encoding(GMime.Stream in_stream) {
+public async GMime.ContentEncoding get_best_encoding(GMime.Stream in_stream,
+ GMime.EncodingConstraint constraint,
+ GLib.Cancellable? cancellable)
+ throws GLib.Error {
GMime.FilterBest filter = new GMime.FilterBest(
GMime.FilterBestFlags.ENCODING
);
- GMime.StreamFilter out_stream = new GMime.StreamFilter(new GMime.StreamNull());
+ GMime.StreamFilter out_stream = new GMime.StreamFilter(
+ new GMime.StreamNull()
+ );
out_stream.add(filter);
- in_stream.write_to_stream(out_stream);
- in_stream.reset();
- return filter.encoding(GMime.EncodingConstraint.7BIT);
+
+ yield Nonblocking.Concurrent.global.schedule_async(() => {
+ in_stream.write_to_stream(out_stream);
+ in_stream.reset();
+ },
+ cancellable
+ );
+ return filter.encoding(constraint);
}
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]