Merge branch 'ss/remove-multilock' into next

This commit is contained in:
Nicolas Sebrecht 2011-01-25 19:19:34 +01:00
commit 0b5d15350d
6 changed files with 21 additions and 60 deletions

View File

@ -246,54 +246,3 @@ class InstanceLimitedThread(ExitNotifyThread):
finally: finally:
if instancelimitedsems and instancelimitedsems[self.instancename]: if instancelimitedsems and instancelimitedsems[self.instancename]:
instancelimitedsems[self.instancename].release() instancelimitedsems[self.instancename].release()
######################################################################
# Multi-lock -- capable of handling a single thread requesting a lock
# multiple times
######################################################################
class MultiLock:
def __init__(self):
self.lock = Lock()
self.statuslock = Lock()
self.locksheld = {}
def acquire(self):
"""Obtain a lock. Provides nice support for a single
thread trying to lock it several times -- as may be the case
if one I/O-using object calls others, while wanting to make it all
an atomic operation. Keeps a "lock request count" for the current
thread, and acquires the lock when it goes above zero, releases when
it goes below one.
This call is always blocking."""
# First, check to see if this thread already has a lock.
# If so, increment the lock count and just return.
self.statuslock.acquire()
try:
threadid = thread.get_ident()
if threadid in self.locksheld:
self.locksheld[threadid] += 1
return
else:
# This is safe because it is a per-thread structure
self.locksheld[threadid] = 1
finally:
self.statuslock.release()
self.lock.acquire()
def release(self):
self.statuslock.acquire()
try:
threadid = thread.get_ident()
if self.locksheld[threadid] > 1:
self.locksheld[threadid] -= 1
return
else:
del self.locksheld[threadid]
self.lock.release()
finally:
self.statuslock.release()

View File

@ -16,10 +16,9 @@
# along with this program; if not, write to the Free Software # along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
from threading import * from threading import RLock, currentThread
from offlineimap.ui.UIBase import UIBase from offlineimap.ui.UIBase import UIBase
import thread import thread
from offlineimap.threadutil import MultiLock
class BlinkenBase: class BlinkenBase:
"""This is a mix-in class that should be mixed in with either UIBase """This is a mix-in class that should be mixed in with either UIBase
@ -85,7 +84,8 @@ class BlinkenBase:
def init_banner(s): def init_banner(s):
s.availablethreadframes = {} s.availablethreadframes = {}
s.threadframes = {} s.threadframes = {}
s.tflock = MultiLock() #tflock protects the s.threadframes manipulation to only happen from 1 thread
s.tflock = RLock()
def threadExited(s, thread): def threadExited(s, thread):
threadid = thread.threadid threadid = thread.threadid

View File

@ -16,7 +16,7 @@
# along with this program; if not, write to the Free Software # along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
from threading import Lock, Event from threading import RLock, Lock, Event
import time import time
import sys import sys
import os import os
@ -32,7 +32,8 @@ acctkeys = '1234567890abcdefghijklmnoprstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ-=;/.,'
class CursesUtil: class CursesUtil:
def __init__(self): def __init__(self):
self.pairlock = Lock() self.pairlock = Lock()
self.iolock = offlineimap.threadutil.MultiLock() # iolock protects access to the
self.iolock = RLock()
self.start() self.start()
def initpairs(self): def initpairs(self):
@ -45,9 +46,20 @@ class CursesUtil:
self.pairlock.release() self.pairlock.release()
def lock(self): def lock(self):
"""Locks the Curses ui thread
Can be invoked multiple times from the owning thread. Invoking
from a non-owning thread blocks and waits until it has been
unlocked by the owning thread."""
self.iolock.acquire() self.iolock.acquire()
def unlock(self): def unlock(self):
"""Unlocks the Curses ui thread
Decrease the lock counter by one and unlock the ui thread if the
counter reaches 0. Only call this method when the calling
thread owns the lock. A RuntimeError is raised if this method is
called when the lock is unlocked."""
self.iolock.release() self.iolock.release()
def locked(self, target, *args, **kwargs): def locked(self, target, *args, **kwargs):

View File

@ -15,10 +15,10 @@
# along with this program; if not, write to the Free Software # along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
import offlineimap.version
import urllib, sys, re, time, traceback, threading, thread import urllib, sys, re, time, traceback, threading, thread
from UIBase import UIBase from UIBase import UIBase
from threading import * from threading import *
import offlineimap
protocol = '6.0.0' protocol = '6.0.0'
@ -173,7 +173,7 @@ class MachineUI(UIBase):
s.outputlock.release() s.outputlock.release()
def init_banner(s): def init_banner(s):
s._printData('initbanner', offlineimap.version.banner) s._printData('initbanner', offlineimap.banner)
def callhook(s, msg): def callhook(s, msg):
s._printData('callhook', msg) s._printData('callhook', msg)

View File

@ -16,10 +16,10 @@
# along with this program; if not, write to the Free Software # along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
import offlineimap.version
import re, time, sys, traceback, threading, thread import re, time, sys, traceback, threading, thread
from StringIO import StringIO from StringIO import StringIO
from Queue import Empty from Queue import Empty
import offlineimap
debugtypes = {'imap': 'IMAP protocol debugging', debugtypes = {'imap': 'IMAP protocol debugging',
'maildir': 'Maildir repository debugging', 'maildir': 'Maildir repository debugging',

View File

@ -24,7 +24,7 @@
from distutils.core import setup from distutils.core import setup
import offlineimap.version import offlineimap
setup(name = "offlineimap", setup(name = "offlineimap",
version = offlineimap.__version__, version = offlineimap.__version__,