[geary/wip/cx-reestablish: 8/8] Prevent concurrent open and closes of remote folder
- From: Jim Nelson <jnelson src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [geary/wip/cx-reestablish: 8/8] Prevent concurrent open and closes of remote folder
- Date: Fri, 16 Jan 2015 18:50:36 +0000 (UTC)
commit 22097a0120b1f9a3eceb33d06cf8e32b743d66ec
Author: Jim Nelson <jim yorba org>
Date: Fri Jan 16 10:50:07 2015 -0800
Prevent concurrent open and closes of remote folder
.../imap-engine/imap-engine-minimal-folder.vala | 45 ++++++++++++++++++++
1 files changed, 45 insertions(+), 0 deletions(-)
---
diff --git a/src/engine/imap-engine/imap-engine-minimal-folder.vala
b/src/engine/imap-engine/imap-engine-minimal-folder.vala
index 11c262e..d78d737 100644
--- a/src/engine/imap-engine/imap-engine-minimal-folder.vala
+++ b/src/engine/imap-engine/imap-engine-minimal-folder.vala
@@ -48,6 +48,8 @@ private class Geary.ImapEngine.MinimalFolder : Geary.Folder, Geary.FolderSupport
private int remote_count = -1;
private uint open_remote_timer_id = 0;
private int reestablish_delay_msec = DEFAULT_REESTABLISH_DELAY_MSEC;
+ private Nonblocking.Mutex open_mutex = new Nonblocking.Mutex();
+ private Nonblocking.Mutex close_mutex = new Nonblocking.Mutex();
public MinimalFolder(GenericAccount account, Imap.Account remote, ImapDB.Account local,
ImapDB.Folder local_folder, SpecialFolderType special_folder_type) {
@@ -570,7 +572,29 @@ private class Geary.ImapEngine.MinimalFolder : Geary.Folder, Geary.FolderSupport
open_remote_timer_id = 0;
}
+ // Open the remote connection using a Mutex to prevent concurrency.
+ //
+ // start_remote_open_now() *should* prevent more than one open from occurring at the same time,
+ // but it's still wise to use a nonblocking primitive to prevent it if that does occur to at
+ // least keep Folder state cogent.
private async void open_remote_async(Cancellable? cancellable) {
+ int token;
+ try {
+ token = yield open_mutex.claim_async(cancellable);
+ } catch (Error err) {
+ return;
+ }
+
+ yield open_remote_locked_async(cancellable);
+
+ try {
+ open_mutex.release(ref token);
+ } catch (Error err) {
+ }
+ }
+
+ // Should only be called when open_mutex is locked, i.e. use open_remote_async()
+ private async void open_remote_locked_async(Cancellable? cancellable) {
// watch for folder closing before this call got a chance to execute
if (open_count == 0)
return;
@@ -747,10 +771,31 @@ private class Geary.ImapEngine.MinimalFolder : Geary.Folder, Geary.FolderSupport
cancellable);
}
+ // Close the remote connection and, if open_count is zero, the Folder itself. A Mutex is used
+ // to prevent concurrency.
+ //
// NOTE: This bypasses open_count and forces the Folder closed, reestablishing a connection if
// open_count is greater than zero
internal async void close_internal_async(Folder.CloseReason local_reason, Folder.CloseReason
remote_reason,
bool flush_pending, Cancellable? cancellable) {
+ int token;
+ try {
+ token = yield close_mutex.claim_async(cancellable);
+ } catch (Error err) {
+ return;
+ }
+
+ yield close_internal_locked_async(local_reason, remote_reason, flush_pending, cancellable);
+
+ try {
+ close_mutex.release(ref token);
+ } catch (Error err) {
+ }
+ }
+
+ // Should only be called when close_mutex is locked, i.e. use close_internal_async()
+ private async void close_internal_locked_async(Folder.CloseReason local_reason,
+ Folder.CloseReason remote_reason, bool flush_pending, Cancellable? cancellable) {
cancel_remote_open_timer();
// only flushing pending ReplayOperations if this is a "clean" close, not forced due to
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]