threading: add comments

Simplify the code.

Signed-off-by: Nicolas Sebrecht <nicolas.s-dev@laposte.net>
This commit is contained in:
Nicolas Sebrecht 2016-05-12 04:27:34 +02:00
parent bf8bfbc872
commit 2611a0ba6a
3 changed files with 26 additions and 11 deletions

View File

@ -204,7 +204,10 @@ class SyncableAccount(Account):
Derives from :class:`accounts.Account` but contains the additional
functions :meth:`syncrunner`, :meth:`sync`, :meth:`syncfolders`,
used for syncing."""
used for syncing.
In multi-threaded mode, one instance of this object is run per "account"
thread."""
def __init__(self, *args, **kwargs):
Account.__init__(self, *args, **kwargs)
@ -239,6 +242,8 @@ class SyncableAccount(Account):
pass # Failed to delete for some reason.
def syncrunner(self):
"""The target for both single and multi-threaded modes."""
self.ui.registerthread(self)
try:
accountmetadata = self.getaccountmeta()

View File

@ -16,24 +16,29 @@
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
from offlineimap.threadutil import threadlist, InstanceLimitedThread
from offlineimap.threadutil import threadlist, InstanceLimitedThread, NORMAL_EXIT
from offlineimap.accounts import SyncableAccount
from threading import currentThread
def syncaccount(threads, config, accountname):
def syncaccount(config, accountname):
"""Return a new running thread for this account."""
account = SyncableAccount(config, accountname)
thread = InstanceLimitedThread(instancename = 'ACCOUNTLIMIT',
target = account.syncrunner,
name = "Account sync %s" % accountname)
thread.setDaemon(True)
thread.start()
threads.add(thread)
return thread
def syncitall(accounts, config):
# Special exit message for SyncRunner thread, so main thread can exit
currentThread().exit_message = 'SYNCRUNNER_EXITED_NORMALLY'
threads = threadlist()
"""The target when in multithreading mode."""
# Special exit message for SyncRunner thread, so main thread can exit.
currentThread().exit_message = NORMAL_EXIT
threads = threadlist() # The collection of threads.
for accountname in accounts:
syncaccount(threads, config, accountname)
# Start a new thread per account and store it in the collection.
threads.add(syncaccount(config, accountname))
# Wait for the threads to finish.
threads.reset()
threads.wait() # Blocks until all accounts are processed.

View File

@ -25,6 +25,9 @@ import os.path
import sys
from offlineimap.ui import getglobalui
NORMAL_EXIT = 'SYNCRUNNER_EXITED_NORMALLY'
######################################################################
# General utilities
######################################################################
@ -70,7 +73,7 @@ class threadlist:
finally:
self.lock.release()
def reset(self):
def wait(self):
while 1:
thread = self.pop()
if not thread:
@ -129,7 +132,7 @@ def threadexited(thread):
raise SystemExit
ui.threadException(thread) # Expected to terminate
sys.exit(100) # Just in case...
elif thread.exit_message == 'SYNCRUNNER_EXITED_NORMALLY':
elif thread.exit_message == NORMAL_EXIT:
return True
else:
ui.threadExited(thread)
@ -157,6 +160,8 @@ class ExitNotifyThread(Thread):
self._exit_stacktrace = None
def run(self):
"""Allow profiling of a run."""
global exitthreads
try:
if not ExitNotifyThread.profiledir: # normal case