Replace uses of Gee.TreeSet where used for sorting
Add new Geary.Iterable::to_sorted_list method that should be more performant than adding elements to a sorted set and sorting one-by-one, use that instead of a TreeSet.
This commit is contained in:
parent
37d2898b73
commit
89642c5283
5 changed files with 66 additions and 18 deletions
|
|
@ -226,11 +226,11 @@ public class ConversationListStore : Gtk.ListStore {
|
||||||
|
|
||||||
// sort the conversations so the previews are fetched from the newest to the oldest, matching
|
// sort the conversations so the previews are fetched from the newest to the oldest, matching
|
||||||
// the user experience
|
// the user experience
|
||||||
Gee.TreeSet<Geary.App.Conversation> sorted_conversations =
|
var sorted_conversations = Geary.traverse(
|
||||||
new Gee.TreeSet<Geary.App.Conversation>(
|
this.conversations.read_only_view
|
||||||
Util.Email.compare_conversation_descending
|
).to_sorted_list(
|
||||||
);
|
Util.Email.compare_conversation_descending
|
||||||
sorted_conversations.add_all(this.conversations.read_only_view);
|
);
|
||||||
foreach (Geary.App.Conversation conversation in sorted_conversations) {
|
foreach (Geary.App.Conversation conversation in sorted_conversations) {
|
||||||
// find oldest unread message for the preview
|
// find oldest unread message for the preview
|
||||||
Geary.Email? need_preview = null;
|
Geary.Email? need_preview = null;
|
||||||
|
|
|
||||||
|
|
@ -328,8 +328,7 @@ public class Geary.Imap.MessageSet : BaseObject {
|
||||||
|
|
||||||
private static int64[] seq_array_to_int64(Gee.Collection<SequenceNumber> seq_nums) {
|
private static int64[] seq_array_to_int64(Gee.Collection<SequenceNumber> seq_nums) {
|
||||||
// guarantee sorted (to maximum finding runs in build_sparse_range())
|
// guarantee sorted (to maximum finding runs in build_sparse_range())
|
||||||
Gee.TreeSet<SequenceNumber> sorted = new Gee.TreeSet<SequenceNumber>();
|
var sorted = traverse(seq_nums).to_sorted_list((a,b) => a.compare_to(b));
|
||||||
sorted.add_all(seq_nums);
|
|
||||||
|
|
||||||
// build sorted array
|
// build sorted array
|
||||||
int64[] ret = new int64[sorted.size];
|
int64[] ret = new int64[sorted.size];
|
||||||
|
|
@ -342,8 +341,7 @@ public class Geary.Imap.MessageSet : BaseObject {
|
||||||
|
|
||||||
private static int64[] uid_array_to_int64(Gee.Collection<UID> msg_uids) {
|
private static int64[] uid_array_to_int64(Gee.Collection<UID> msg_uids) {
|
||||||
// guarantee sorted (to maximize finding runs in build_sparse_range())
|
// guarantee sorted (to maximize finding runs in build_sparse_range())
|
||||||
Gee.TreeSet<UID> sorted = new Gee.TreeSet<UID>();
|
var sorted = traverse(msg_uids).to_sorted_list((a,b) => a.compare_to(b));
|
||||||
sorted.add_all(msg_uids);
|
|
||||||
|
|
||||||
// build sorted array
|
// build sorted array
|
||||||
int64[] ret = new int64[sorted.size];
|
int64[] ret = new int64[sorted.size];
|
||||||
|
|
|
||||||
|
|
@ -59,6 +59,9 @@ public class Geary.RFC822.MailboxAddresses :
|
||||||
|
|
||||||
private Gee.List<MailboxAddress> addrs = new Gee.ArrayList<MailboxAddress>();
|
private Gee.List<MailboxAddress> addrs = new Gee.ArrayList<MailboxAddress>();
|
||||||
|
|
||||||
|
private bool hash_cached = false;
|
||||||
|
private uint hash_value = 0;
|
||||||
|
|
||||||
|
|
||||||
public MailboxAddresses(Gee.Collection<MailboxAddress>? addrs = null) {
|
public MailboxAddresses(Gee.Collection<MailboxAddress>? addrs = null) {
|
||||||
if (addrs != null) {
|
if (addrs != null) {
|
||||||
|
|
@ -170,17 +173,22 @@ public class Geary.RFC822.MailboxAddresses :
|
||||||
}
|
}
|
||||||
|
|
||||||
public uint hash() {
|
public uint hash() {
|
||||||
// create sorted set to ensure ordering no matter the list's order
|
if (!this.hash_cached) {
|
||||||
Gee.TreeSet<string> sorted_addresses = traverse<RFC822.MailboxAddress>(addrs)
|
// Sort the addresses to ensure a stable hash
|
||||||
.map<string>(m => m.address)
|
var sorted_addresses = traverse<RFC822.MailboxAddress>(addrs)
|
||||||
.to_tree_set(String.stri_cmp);
|
.map<string>(m => m.address)
|
||||||
|
.to_sorted_list(String.stri_cmp);
|
||||||
|
|
||||||
// xor all strings in sorted order
|
// xor all strings in sorted order
|
||||||
uint xor = 0;
|
uint xor = 0;
|
||||||
foreach (string address in sorted_addresses)
|
foreach (string address in sorted_addresses) {
|
||||||
xor ^= address.hash();
|
xor ^= address.hash();
|
||||||
|
}
|
||||||
|
this.hash_value = xor;
|
||||||
|
this.hash_cached = true;
|
||||||
|
}
|
||||||
|
|
||||||
return xor;
|
return this.hash_value;
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool equal_to(MailboxAddresses other) {
|
public bool equal_to(MailboxAddresses other) {
|
||||||
|
|
|
||||||
|
|
@ -225,6 +225,19 @@ public class Geary.Iterable<G> : BaseObject {
|
||||||
return (Gee.ArrayList<G>) add_all_to(new Gee.ArrayList<G>((owned) equal_func));
|
return (Gee.ArrayList<G>) add_all_to(new Gee.ArrayList<G>((owned) equal_func));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a new list containing all elements, sorted.
|
||||||
|
*
|
||||||
|
* The ordering is applied after adding all elements to the list,
|
||||||
|
* so as to minimise computational overhead.
|
||||||
|
*/
|
||||||
|
public Gee.ArrayList<G> to_sorted_list(owned GLib.CompareDataFunc<G> comparator,
|
||||||
|
owned Gee.EqualDataFunc<G>? equal_func = null) {
|
||||||
|
var list = to_array_list((owned) equal_func);
|
||||||
|
list.sort((owned) comparator);
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
|
||||||
/** Returns a new linked list containing all elements. */
|
/** Returns a new linked list containing all elements. */
|
||||||
public Gee.LinkedList<G> to_linked_list(owned Gee.EqualDataFunc<G>? equal_func = null) {
|
public Gee.LinkedList<G> to_linked_list(owned Gee.EqualDataFunc<G>? equal_func = null) {
|
||||||
return (Gee.LinkedList<G>) add_all_to(new Gee.LinkedList<G>((owned) equal_func));
|
return (Gee.LinkedList<G>) add_all_to(new Gee.LinkedList<G>((owned) equal_func));
|
||||||
|
|
|
||||||
|
|
@ -13,6 +13,7 @@ class Geary.RFC822.MailboxAddressesTest : TestCase {
|
||||||
add_test("from_rfc822_string_quoted", from_rfc822_string_quoted);
|
add_test("from_rfc822_string_quoted", from_rfc822_string_quoted);
|
||||||
add_test("to_rfc822_string", to_rfc822_string);
|
add_test("to_rfc822_string", to_rfc822_string);
|
||||||
add_test("equal_to", equal_to);
|
add_test("equal_to", equal_to);
|
||||||
|
add_test("hash", hash);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void from_rfc822_string_encoded() throws Error {
|
public void from_rfc822_string_encoded() throws Error {
|
||||||
|
|
@ -82,6 +83,34 @@ class Geary.RFC822.MailboxAddressesTest : TestCase {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void hash() throws Error {
|
||||||
|
var mailboxes_a = new_addreses({ "test1@example.com" });
|
||||||
|
var mailboxes_b = new_addreses({ "test1@example.com" });
|
||||||
|
var mailboxes_c = new_addreses({ "test2@example.com" });
|
||||||
|
|
||||||
|
assert_true(mailboxes_a.hash() == mailboxes_a.hash());
|
||||||
|
assert_true(mailboxes_a.hash() == mailboxes_b.hash());
|
||||||
|
assert_false(mailboxes_a.hash() == mailboxes_c.hash());
|
||||||
|
|
||||||
|
assert_true(
|
||||||
|
new_addreses({ "test1@example.com", "test2@example.com" }).hash() ==
|
||||||
|
new_addreses({ "test1@example.com", "test2@example.com" }).hash()
|
||||||
|
);
|
||||||
|
assert_true(
|
||||||
|
new_addreses({ "test1@example.com", "test2@example.com" }).hash() ==
|
||||||
|
new_addreses({ "test2@example.com", "test1@example.com" }).hash()
|
||||||
|
);
|
||||||
|
|
||||||
|
assert_false(
|
||||||
|
new_addreses({ "test1@example.com", "test2@example.com" }).hash() ==
|
||||||
|
new_addreses({ "test1@example.com" }).hash()
|
||||||
|
);
|
||||||
|
assert_false(
|
||||||
|
new_addreses({ "test1@example.com", "test2@example.com" }).hash() ==
|
||||||
|
new_addreses({ "test1@example.com", "test3@example.com" }).hash()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
private MailboxAddresses new_addreses(string[] address_strings) {
|
private MailboxAddresses new_addreses(string[] address_strings) {
|
||||||
Gee.List<MailboxAddress> addresses = new Gee.LinkedList<MailboxAddress>();
|
Gee.List<MailboxAddress> addresses = new Gee.LinkedList<MailboxAddress>();
|
||||||
foreach (string address in address_strings) {
|
foreach (string address in address_strings) {
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue